Reliable API automation
This page defines the safe operating contract for a developer or AI agent that changes a Moltaro workspace through its APIs. It starts after the workspace owner has prepared access in the Moltaro Portal or administrative Web Application interface.
Required handoff
Section titled “Required handoff”The workspace owner gives the developer or agent:
- the downloaded workspace-specific
AGENTS.mdorCLAUDE.md; - the exact
WORKSPACE_API_BASE_URL; - an API key through an appropriate secret channel;
- a task and an account with the narrowest roles needed for that task.
The guide must not contain the key. A missing URL, guide, key, or permission is an administrative prerequisite, not an API-discovery problem.
This prerequisite boundary does not remove the configured Application’s
administrative APIs from the agent workflow. Once authenticated with the
provided roles, the agent uses documented /api/workspace/admin/...
Configuration API routes for entity definitions, Net Operation Project,
Boards and Entitlement configuration, Agent integration, and Workspace UI.
Those are workspace Application endpoints. Portal administration endpoints
are a different surface and are not part of the developer contract.
Keep the public and workspace origins visibly separate in scripts and prompts:
PUBLIC_DOCS_BASE=https://moltaro.comWORKSPACE_API_BASE_URL=https://customer-workspace-api.example.comPUBLIC_DOCS_BASE is for documentation only. Every /api/workspace/... and
installation-local /openapi/... path resolves against
WORKSPACE_API_BASE_URL. The Web Application used by people may have another
origin; never derive the API hostname from it.
Preflight every workspace
Section titled “Preflight every workspace”Before changing anything:
GET ${WORKSPACE_API_BASE_URL}/api/workspace/contextGET ${WORKSPACE_API_BASE_URL}/api/workspace/auth/meGET ${WORKSPACE_API_BASE_URL}/openapi/moltaro-public-v1.jsonGET ${WORKSPACE_API_BASE_URL}/openapi/moltaro-config-v1.jsonGET ${WORKSPACE_API_BASE_URL}/api/workspace/admin/net-operation-project/developer-surfaceAfter this handoff, the authenticated Application endpoints below may also be used to refresh the installation manifest or generated guide:
GET ${WORKSPACE_API_BASE_URL}/api/workspace/admin/agent-integrationGET ${WORKSPACE_API_BASE_URL}/api/workspace/admin/agent-integration/agents-mdThey do not discover an unknown workspace; they require the API base URL and authorized key that the user already supplied.
Read the workspace locale and time zone, the caller’s roles and module states,
the installed API contract, and the supported C# surface. Treat the
installation-local OpenAPI documents and developer-surface response as
authoritative for that workspace. Do not infer an endpoint, enum value,
injectable service, or module availability from a different release or from a
public CLR type.
Safe operating loop
Section titled “Safe operating loop”Use the same sequence for schema, records, C# logic, Boards, Entitlement Operations, and custom pages:
- Discover the installed contract, entity schema, module state, current revision, and permissions.
- Read before writing. Capture ids, stable keys, row versions, source checksums, and file hashes from current responses.
- Preview where supported. Use schema-change plans, source-template preview, page-generator preview, validation, and language diagnostics before creating a revision or changing data.
- Make one bounded change. Keep a stable external correlation or idempotency key when the operation supports one.
- Verify the saved state. Read the entity, revision, source index, board item, entitlement history, or generated artifact back from the API.
- Check before publishing. Net Operation Project Build activates on success; Workspace UI Build does not. Use their exact lifecycles below.
- Verify the runtime result and history. Check the Function Catalog or active artifact, invoke only when requested, and read the relevant audit or ledger surface.
Do not delete schema, purge artifacts, deactivate pages, rotate credentials, or activate code merely because an endpoint exists. Those actions require an explicit task. For a destructive schema change, inspect the server-provided change plan and surface its data-loss warnings before proceeding.
Concurrency and HTTP 409
Section titled “Concurrency and HTTP 409”Moltaro rejects stale writes instead of silently overwriting newer work:
- record updates use the last observed
RowVersion; - Net Operation Project manual edits use
BaseRevisionId,BaseSourceChecksum, andExpectedContentHashfor every changed existing file; - Workspace UI source edits use the same base revision/checksum pattern and file hashes where the request schema requires them;
- artifact activation, deactivation, rollback, and purge use expected project and artifact row versions.
On HTTP 409, do not resend the old body. Re-read the object or source tree,
compare the intervening change with the intended change, merge when safe, and
submit a new request using the fresh concurrency values. If the correct merge
is ambiguous, stop and ask the user.
Retries, idempotency, and stable keys
Section titled “Retries, idempotency, and stable keys”- Retry reads after a transient transport failure.
- Do not blindly retry a mutation after an unknown outcome. First read the target state or use the operation’s documented idempotency key.
- Boards automation commands mirror Runtime API semantics and do not have a
separate durable receipt. After an unknown add outcome, query the open item;
after an unknown mutation outcome, read the item and compare its current
state and
RowVersionbefore deciding whether another command is needed. - Reuse the same durable idempotency key when retrying the same logical
Entitlement grant, renewal, lifecycle, consume, reverse, adjustment, or
renewal-operation command. Do not generate a new key for each attempt. The
Entitlement facade reports a native durable replay as
Replayed = true. - A source template’s
StableKeyidentifies the published function or data source across revisions. Read the template catalog to learn whether it is required; do not derive it from a display name. - A command
CorrelationIdconnects one external operation with its run and downstream history. It is observability context, not a substitute for an operation-specific idempotency key. - Validation, permission, not-found, and concurrency responses require a corrected request or fresh state, not automatic retry.
Polling checks, builds, and jobs
Section titled “Polling checks, builds, and jobs”Queue a build once, retain its returned id, and poll that exact resource with
a bounded delay and overall client deadline. Do not queue duplicate builds
because a build remains Queued or Running longer than expected.
First establish that the operation is actually queued. A C# Task, an
Async method name, or HTTP 200 is not an execution-mode signal: Moltaro
enqueue endpoints return a normal success envelope containing a queued
resource. Use Function Catalog contract, binding source, API publication kind,
schedule metadata, and the response schema. The complete discovery table,
CRON flow, job/run distinction, and polling algorithm are in
Asynchronous operations and polling.
Both project build status enums use Queued = 0, Running = 1,
Succeeded = 2, Failed = 3, and Cancelled = 4. 2, 3, and 4 are
terminal. On failure, read the stored diagnostics rather than immediately
submitting an identical build.
The build kinds and activation behavior are different:
| Project | Check | Build | Activation |
|---|---|---|---|
| Net Operation Project | 1 | 0 | A successful Build automatically replaces the active C# artifact. A failed Build leaves the previous artifact active. |
| Workspace UI Project | 0 | 1 | Build creates an inactive artifact. Activation is a separate, row-version-protected operation; rollback can restore a compatible prior artifact. |
Function jobs use Queued = 0, Leased = 1, Completed = 2, Failed = 3,
and Cancelled = 4. Poll the job id returned by enqueue; do not enqueue the
same business operation again simply because it is still queued or leased.
For recurring work, create one Function Schedule through the Configuration
API instead of running a client-side timer that repeatedly calls a manual
enqueue endpoint. The schedule processor leases each due occurrence and the
function queue suppresses a new scheduled job while the target function has
queued or running work. That due occurrence remains visible as a diagnostic
Skipped run. Do not add another singleton or deduplication layer and do not
submit a compensating manual job for Skipped; observe the active job and let
the next CRON occurrence proceed normally.
Generated entity contract after schema changes
Section titled “Generated entity contract after schema changes”Moltaro regenerates GeneratedWorkspaceContract on the server. Each C#
language request and Check/Build receives the current generated entity source;
there is no contract download or refresh endpoint in the API-first workflow.
After creating, changing, or deleting an entity field:
- read the entity definition again and use its current keys and ids;
- call completions, hover, signature help, or diagnostics again for the current source buffer;
- fix any renamed or removed generated members;
- if the source changed, create a new immutable source revision; run Check against the exact revision before Build.
Do not continue from completion results captured before the schema change.
Net Operation Project source limits
Section titled “Net Operation Project source limits”The current source contract accepts at most 500 files, 512 KiB of UTF-8 text
per file, 5 MiB of UTF-8 source in total, and 500 changes in one manual-edit
request. Paths are relative, use /, and are at most 512 characters. Supported
stored paths are:
- C# files below
src/; - Markdown at the project root or below
docs/; - root
package-references.json, with at most 50 package references.
Generated, build, dependency, and repository directories such as
GeneratedWorkspaceContract, bin, obj, lib, node_modules, .git,
and .moltaro cannot be edited through the source API. Language requests use
the same 512 KiB active-buffer and 5 MiB snapshot limits.
Successful diagnostics and manual-edit responses include Limits, which is
the machine-readable contract for source size, manual-edit count, diagnostics
timeout, manual-edit timeout, and diagnostics concurrency. A size rejection
includes safe MaxBytes and ActualBytes metadata without source text.
File-count and manual-edit-count rejections likewise include exact maximum and
actual counts.
Diagnostics that exceed the server deadline return HTTP 503 with
netOperationProject.language.analysis.timeout. A manual edit that exceeds its
deadline or cannot acquire the project write lock in time returns HTTP 503
with netOperationProject.source.manualEdit.timeout; it creates no revision.
After either response, read current status and retry with current concurrency
values. Client cancellation may leave analysis completing safely in the
background, but it does not retain the project write lock or block status
reads. An ExpectedContentHash mismatch is a distinct HTTP 409 response.
Data and error conventions
Section titled “Data and error conventions”- JSON properties are PascalCase and public enums are numeric. Read
x-enum-varnamesfrom the installed OpenAPI document instead of guessing a number. - Check the response envelope’s
Successbefore usingData. Branch on the stable errorCodeand optionalField, never on localizedMessage. - Read locale and time zone from
/api/workspace/context. Send dates, times, decimals, and currency values in the exact JSON shape declared by OpenAPI; never apply locale-specific display formatting to an API value. - A
403can mean the account lacks a role or resource-context permission. The agent asks the user or workspace administrator to review access; it does not attempt to grant itself permissions.
Recovery guide
Section titled “Recovery guide”| Symptom | Safe response |
|---|---|
401 | Confirm the request used WORKSPACE_API_BASE_URL and the provided bearer key. If the key is missing, expired, or revoked, ask the user to update it in the Portal or administrative interface. |
403 | Read the operation’s permission requirements and ask the administrator for the narrowest missing permission. Do not switch to a personal login or change roles yourself. |
404 | First verify the API origin. Then re-discover the entity, function, board, module resource, or artifact; ids and visibility are workspace-specific. |
409 | Re-read, compare, merge, and retry with fresh row versions, revision ids, checksums, and hashes. Never overwrite blindly. |
Net Operation Project source processing returns 503 | For netOperationProject.language.analysis.timeout or netOperationProject.source.manualEdit.timeout, read current status, respect the returned retry metadata and Limits, then retry from fresh revision, checksum, and file-hash values. A timed-out manual edit creates no revision. |
| Diagnostics pass but Check fails | Diagnostics replace one unsaved buffer inside a revision snapshot. Save every intended file, then inspect Check diagnostics for the exact immutable revision and installed dependencies. |
| Check passes but Build fails | Read the stored Build stage and nullable structured Failure. Branch on ReasonCode, not the localized summary. The previous Net Operation Project artifact remains active. For storage_capacity_exhausted, ask the operator to free or expand storage before queueing a new Build. For publication_commit_unconfirmed, re-read the Build and active artifact before retrying; do not repair catalog rows manually. Workspace UI never activates a failed build. |
| Workspace UI Build succeeds but users see no change | Find the artifact by BuildId and RevisionId, activate it with current row versions, then perform the required full WebApp refresh. |
| Module is disabled or an injectable service is absent | Read workspace module state and developer-surface. Ask the administrator to enable/configure the supported module, or remove the dependency. Do not inject an unlisted internal service. |
moltaro.automation.executionPhase.unsupported | Move the module operation out of Validation/BeforeSaveMutation and into an Action, TriggerHandler, Command, Job, or HttpEndpoint. Prefer an after-commit trigger when it depends on a saved record. |
| Polling reaches the client deadline | Keep the build or job id, report its latest state, and let the user decide whether to continue polling or request cancellation. Do not enqueue a duplicate. |
Audit responsibility
Section titled “Audit responsibility”| Change path | History behavior |
|---|---|
| Runtime record create/update/archive through Moltaro APIs and product surfaces | The platform writes field, table, assignment, and system-field history when audit is enabled for the entity definition. |
| Net Operation Project direct-DB save | Automatic field-level audit is not added. Emit a display-safe AddBusinessEventAsync event for each meaningful custom state change. |
| Boards application-automation operation | Stored actor is moltaro-system-automation; join Function operations to board history/resource events by correlation and origin metadata. |
| Entitlement application-automation operation | Stored actor is moltaro-system-automation; treat the append-only ledger and entitlement history as truth and join them to the function run by correlation/origin metadata. |
| Net Operation Project or Workspace UI publication | Project build and publication governance is separate from one record’s change feed. Verify the active artifact through the project APIs. |
See Record history and audit for the record change feed and business-event recipe, and Errors and responses for the common response shape.