AI agent development quickstart
An AI coding agent can develop a Moltaro workspace without downloading a
project or reading product source code. The generated AGENTS.md and
CLAUDE.md are intentionally compact bootstrap guides: they identify the
workspace, credentials, safety rules, and authoritative sources instead of
repeating feature playbooks. Use the full agent-readable documentation for
product semantics and examples, the installation’s two OpenAPI documents for
exact HTTP contracts, and the server-side C# language service for source work.
Load .moltaro/credentials.env and use MOLTARO_API_KEY as a bearer token.
The generated identity has Admin and Configurator access for the authoring
operations on this page. Never put the key in source, prompts, logs, or
generated output, and never try to create, rotate, or expand the account’s
permissions yourself.
Read the installed release context first
Section titled “Read the installed release context first”Before starting or resuming work, fetch
llms-manifest.json, record its ProductVersion
and DocumentationVersion, and open the matching detail page from the
versioned release notes. Read the summary,
detailed changes, migrations, operator actions, and compatibility guidance for
that version. Repeat the check when the manifest version or HTTP ETag
changes. Release notes explain what changed; the current documentation and the
installation-local OpenAPI remain authoritative for supported behavior and
exact request shapes.
For hierarchical records, follow the installation-safe discovery, configure, read-back, root/child, filter, and picker sequence in the Parent Tree View developer guide. For an embedded child table on a Form, follow the complete options, read-modify-write-read, YAML, locked-filter, security, and concurrency workflow in the Form Related Table guide; never invent its inverse target or submit a client-owned child filter.
1. Connect to the configured workspace
Section titled “1. Connect to the configured workspace”Read WORKSPACE_API_BASE_URL from the downloaded guide. Every route on this
page that starts with /api/workspace/ or /openapi/ is relative to that
URL, never to https://moltaro.com.
The guide and contracts for the configured installation are:
GET ${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-surfacedeveloper-surface is the machine-readable catalog of supported assemblies,
versions, injectable service types, lifetimes, module keys, and .NET reference
links. Do not infer support from every public CLR type in a DLL.
The following are Moltaro Application Configuration API endpoints, not Portal endpoints:
GET ${WORKSPACE_API_BASE_URL}/api/workspace/admin/agent-integrationGET ${WORKSPACE_API_BASE_URL}/api/workspace/admin/agent-integration/agents-mdPOST ${WORKSPACE_API_BASE_URL}/api/workspace/admin/agent-integration/access-kitAn authenticated agent may call the two read endpoints after the handoff to
re-read the installation manifest or generated guide. The access-kit
operation belongs to the administrator’s one-time handoff and must not be
called by the agent to provision or elevate itself. These routes cannot
discover an unknown workspace; the caller must already know
WORKSPACE_API_BASE_URL and have permission.
The same distinction applies to all /api/workspace/admin/... routes in this
guide: they are supported administrative APIs of the configured Application
and remain part of the agent development workflow.
2. Create and inspect an entity
Section titled “2. Create and inspect an entity”Follow the Configuration quickstart to create the entity definition and its fields. Then read it back before writing code:
GET /api/workspace/entity-definitionsGET /api/workspace/entity-definitions/{entityDefinitionId}Field keys, ids, types, and generated CLR names are data from the installation; never guess them.
Searchability is also explicit installation data. Read the administrative
definition’s SearchTargets, SearchMaxPathDepth, and RowVersion, then use
the replace-all search-targets operation when the requested solution needs
record search. Do not generate legacy full-text flags or a rebuild step. The
Entity search contract contains the exact
Configuration API and runtime SearchTerm payloads.
When authoring a Reference field through the Configuration API, use the
installed OpenAPI enum metadata and choose deletion semantics explicitly:
ReferenceDeleteBehavior is 0 None, 1 Cascade, or 2 Restrict. New
references default to Restrict. A blocked permanent delete returns HTTP 409
with moltaro.instances.delete.referenced; branch on the stable code rather
than its localized message. See
Configuration API quickstart.
YAML has the same semantics: omission means Restrict for a newly imported
Reference or a non-reference field converted to Reference, and preserves the
current value when updating a matched Reference; exports contain the effective
value.
After any schema change, read the entity again and call the language endpoints
again. Every request receives the current server-generated
GeneratedWorkspaceContract; completion results captured before a field was
added, renamed, or removed are stale.
3. Preview a C# source template
Section titled “3. Preview a C# source template”List templates first because the response states the default folder and which inputs each template requires:
GET /api/workspace/admin/net-operation-project/source-templatesPOST /api/workspace/admin/net-operation-project/source-templates/previewThe preview does not create a revision. Entity-bound templates accept a target entity definition id and return source using the current generated CLR type.
4. Explore the generated contract in an unsaved buffer
Section titled “4. Explore the generated contract in an unsaved buffer”Send the current Content, source Path, and one-based cursor position to:
POST /api/workspace/admin/net-operation-project/source-language/completionsPOST /api/workspace/admin/net-operation-project/source-language/hoverPOST /api/workspace/admin/net-operation-project/source-language/signature-helpMoltaro automatically adds the current GeneratedWorkspaceContract to every
Roslyn snapshot using the same two-project graph, controlled references,
language options, and analyzers as Check. Send the CurrentSchemaContractHash
from GET .../status as SchemaContractHash on every source-language request.
If the schema changes meanwhile, Moltaro returns HTTP 409 with
netOperationProject.language.schemaContract.stale; re-read status, schema,
and the source buffer before retrying. Hover and signature help also read XML
documentation for the supported SDK and active module assemblies. There is no
generated-contract download or edit step in the agent workflow.
Before writing module code, inspect developer-surface. For Boards,
Entitlement Operations, and Work Schedule, choose the entries with
ServiceKind: ApplicationAutomation and Preferred: true:
IBoardAutomationCommandService / IBoardAutomationQueryServiceIEntitlementAutomationCommandService / IEntitlementAutomationQueryServiceIWorkScheduleAutomationCommandService / IWorkScheduleAutomationQueryServiceThese services need no manually assembled actor, role set, or Board Data.
They run the complete application flow as moltaro-system-automation, retain
the original user/function run/correlation in origin metadata, and commit in
a separate application scope. Use them only from Action, TriggerHandler,
Command, Job, or HttpEndpoint code; Validation and BeforeSaveMutation return
moltaro.automation.executionPhase.unsupported. Entitlement commands need a
stable business IdempotencyKey. Boards commands deliberately mirror Runtime
API behavior without a separate receipt, except Board admission requires a
caller-owned UUID OperationKey. Preserve it for an exact retry after an
unknown outcome; exact replay returns the original item and changed-payload
reuse conflicts. Query the current Board item before starting another logical
admission. Returned
RowVersion values are concurrency tokens for later mutations.
For Work Schedule, read the
Work Schedule C# guide and the generated
Work Schedule XML reference.
Use a new stable OperationId for each logical command and preserve it only for
an exact retry. Calendar writes use the current RowVersion; assignment and
exception changes use the last returned ChainVersion. Requests never accept
an actor or authority tier. Do not model Operational Location as an exception
scope: the supported scopes are Workspace, Site, and Worker.
Inside one explicit function transaction, invoke a Boards command before
staging or saving Entity or owned-table mutations. An Entity-first sequence is
rejected with moltaroBoards.runtime.entityMutationBeforeBoardCommandUnsupported
before the Boards facade opens its separate application scope. Start a new
transaction instead of retrying the same ordering.
Boards may have enabled event and status-invariant Constraints. Treat every ordered runtime
Errors[] entry as authoritative: branch on Code, retain Target and safe
Metadata in diagnostics, and show the workspace-authored Message to the
operator without attempting value interpolation. ValidateMoveAsync returns
CapturedAtUtc and ordered ConstraintDecisions, but it is only a dry run;
execute with the current RowVersion and handle a newly rejected result. Never
retry a rejected Constraint as though it were a transient transport failure.
Normal generated-context MoltaroDbContext.SaveChanges[Async] also runs every
registered Entity pre-commit provider. A rejection throws
MoltaroPreCommitSaveRejectedException; catch it only when the function must
shape a controlled domain result, and branch on its ordered Errors[].Code
values rather than its message. If function code does not catch it, Moltaro
records the run as ValidationFailure, copies the safe provider errors into
the run’s validation errors, and sets FailureReasonCode to the stable
moltaro.preCommit.rejected. This is a business rejection, not a transient
failure. The exact public namespace is
Moltaro.Package.NET.ModuleRuntime.Runtime; generated code that catches the
exception must include:
using Moltaro.Package.NET.ModuleRuntime.Runtime;The run-level failure code is deliberately general. One rejected save may
contain several provider failures, so code that needs the specific reasons
must inspect every ordered Errors[].Code value instead of expecting one
exception-level reason code. Inside one explicit transaction, stage every Entity identity in a
cross-record unit of work before the first SaveChanges; introducing a new
identity in a later save is rejected before lock acquisition. This rule is
global to generated-context Entity writes, not conditional on Board usage.
Assign all new string ids up front, connect the complete related graph in
memory, and issue one SaveChangesAsync. Do not generate sequential-save code
merely to obtain a parent’s id. Use the
atomic related-graph recipe
when generating an import or cross-record command.
5. Diagnose the unsaved buffer
Section titled “5. Diagnose the unsaved buffer”POST /api/workspace/admin/net-operation-project/source-language/diagnosticsContent-Type: application/json
{ "RevisionId": "working-revision-id", "Path": "src/Functions/CloseTicket.cs", "Content": "// complete current C# buffer", "SchemaContractHash": "hash returned by GET .../status"}Diagnostics compile the supplied buffer together with the other files in the
revision. They do not save, build, or activate anything. Each diagnostic has a
stable Code, Severity, Origin (Source or GeneratedContract), and a
source Path and Range when Roslyn provides a location. Treat any generated
contract error as a platform/schema problem; do not rewrite unrelated user
source to hide it.
On success, read Limits rather than assuming source-size, timeout, or
concurrency values. HTTP 503 with
netOperationProject.language.analysis.timeout is terminal for that request:
read status and retry from the current revision after the returned bound. If
the client cancels, Moltaro safely finishes cleanup in the background without
holding the project write lock.
6. Create an immutable revision
Section titled “6. Create an immutable revision”Read GET .../status, then submit BaseRevisionId, BaseSourceChecksum, and
file changes to POST .../source-revisions/manual-edit. For an existing file,
also send its ExpectedContentHash. A stale revision or checksum returns HTTP
409; a stale file hash does as well. Re-read the source instead of overwriting
another change. Successful manual edits return the new revision id, checksum,
and effective Limits. HTTP 503 with
netOperationProject.source.manualEdit.timeout creates no revision; read
status and retry from fresh revision, checksum, and file-hash values.
Read GET .../source-language/source-index?revisionId=... after saving to
verify the functions, data sources, services, bindings, keys, and diagnostics
Moltaro discovered.
7. Check, build, and invoke
Section titled “7. Check, build, and invoke”Net Operation Project numeric values are:
| Kind | Value | Effect |
|---|---|---|
| Build | 0 | Compile and automatically activate the successful artifact |
| Check | 1 | Compile only; never activate an artifact |
Post-schema-change artifact checkpoint
Section titled “Post-schema-change artifact checkpoint”After any schema-affecting change, and before handing off C# business logic, read:
GET /api/workspace/admin/net-operation-project/statusInspect CurrentSchemaContractHash, IsActiveArtifactSchemaStale, and
NeedsValidation, together with ActiveArtifact.SchemaContractHash. These
values are independent. A stale active artifact was compiled against an older
contract but may still be running. NeedsValidation = false does not prove
that the active artifact is current. A successful Check may clear
NeedsValidation, but it compiles only and cannot clear the stale-artifact
warning. A successful Build activates the replacement; a failed Build
preserves the previous active artifact.
When IsActiveArtifactSchemaStale is true, use the exact intended revision
from the fresh status, normally WorkingRevision.Id:
- Queue Check (
Kind: 1), retain its build id, and poll that exact build to terminalSucceeded,Failed, orCancelled. Inspect the terminal result and diagnostics. Stop without queueing Build unless Check succeeded. - Queue Build (
Kind: 0) for the same revision, retain its build id, and poll that exact build to a terminal result. - Read status again and require
IsActiveArtifactSchemaStale = falseplus a non-emptyActiveArtifact.SchemaContractHashequal toCurrentSchemaContractHashbefore handoff.
If a matching operation is already queued or running, poll it instead of
enqueueing a duplicate. Never select another revision merely because a stale
warning exists. If the schema changes again during the sequence, re-read
status and restart the decision from the new current contract. The API-first
workflow does not download or edit GeneratedWorkspaceContract.
Queue POST .../builds with the saved RevisionId and Kind: 1, then poll
GET .../builds/{buildId}. When Check succeeds, queue Kind: 0. A failed Build
leaves the previous active artifact running.
Verify the result in GET /api/workspace/admin/function-catalog, then invoke a
published command with POST /api/workspace/commands/{functionKey} or enqueue
a published job with POST /api/workspace/functions/{functionKey}/enqueue.
Before invoking it, determine the execution model from the installed API:
CurrentPublishedContract in the Function Catalog, Source on entity
bindings, and Kind in GET /api/workspace/admin/api-functions. For a CRON
schedule, join its BusinessFunctionId to the catalog; a valid target is a
global Job function, and each due occurrence is queued for a worker. C#
async/Task and HTTP 200 do not distinguish blocking from queued work.
See Asynchronous operations and polling
for the complete decision table and schedule-observation flow.
Do not queue another build merely because one remains queued or running. Poll the returned build id until a terminal status and inspect stored diagnostics on failure. Preserve stable keys across source revisions and reuse a durable idempotency key when retrying the same supported business operation.
Continue with the verified C# recipes for entity events, Boards, Entitlement Operations, and Currency Rates. Read record history through the audit API. Use Reliable API automation for the complete retry, concurrency, polling, recovery, source-limit, and safety rules.
Complete a user-facing entity UI
Section titled “Complete a user-facing entity UI”Creating an entity schema is not the completion boundary for a user-facing
record type. Configure localized presentation, table/card/form leaf surfaces,
Entity List, Details and Drawer hosts, valid selectors, reachable
Preview/OpenDetails navigation, menu placement, and least-privilege
permissions. Read every configuration back and verify it as both an
administrator and an ordinary reader when test identities are available.
Default selectors may validly use SurfaceKey = null and resolve the
configured default. CustomKey always requires an existing compatible key.
Read the Runtime screens
and UI surface library
guides for the full product model, then use the installation-local
Configuration OpenAPI for exact requests. The generated agent guide routes to
these sources and intentionally does not duplicate this feature-specific
workflow. The Workspace UI Project is for custom pages and is not a
replacement for completing built-in entity surfaces.
Design table filters and sorting
Section titled “Design table filters and sorting”Before configuring a table, read its
/ui/table-surfaces/configuration/options response and choose FilterItems,
SortItems, and DefaultSort from the returned typed targets. Do not guess
field paths or infer query behavior from the column renderer. Visible business
dimensions that users need to segment or order by—especially statuses and other
references—should normally support both operations unless an omission has a
recorded rationale.
Reference targets are not interchangeable. A root Status target is distinct
from the value displayed to users; Status/Name sorts by its label, while
Status/SortOrder is meaningful only when the referenced records actually
contain a business order. Use technical paths from the options response and
localize only the workspace-authored labels.
Related targets are identified by their complete path. Copy the entire
configured Target.Path into runtime conditions; never replace it with
ReferencePath, which controls lookup breadcrumb rendering only. See
Table filters and sorting and
Entity Instance Query.
Read the saved configuration back and verify labels, visibility,
VisibleByDefault, item order, typed paths, and DefaultSort. In the Web
Application, apply a representative filter and sort and verify totals, every
visible row value, and ordering—not merely that the choices appear in a drawer.
Then clear the test filter and restore the intended default sort. When possible,
repeat the query as an ordinary reader and confirm that inaccessible fields,
records, and result counts remain protected by server-side permissions.
8. Use managed secrets safely
Section titled “8. Use managed secrets safely”When trusted C# needs an outbound credential, first inspect
developer-surface for Moltaro.Package.NET.Functions.ISecretService. Inject
that service into the function constructor and use its synchronous
GetRequired(key) or TryGet(key, out value) methods. Do not invent an async
secret API, pass the value in function arguments, or place it in source.
The owner or administrator supplies exact key names and enters values directly through Administration > Secrets or an explicitly authorized write-only API flow. The agent does not need the values: it creates the source revision, runs Check and Build, invokes the intended function flow, reports only a non-secret business marker, and asks the owner to confirm Audit Trail evidence. Provisioning, rotation, external-system changes, rollout, and schedule enablement remain separate owner/operator actions unless the task explicitly authorizes them.
Only an owner or administrator can manage keys through
/api/workspace/admin/secrets; Configurator access is not sufficient. An agent
must not list, create, rotate, disable, enable, or retire keys unless the user
explicitly authorizes that administration work. There is no reveal endpoint.
Trusted C# can resolve every active key it knows. Never log, persist, return,
or copy resolved values or derived bearer tokens. Required unavailable values
raise stable moltaro.secrets.missing, moltaro.secrets.disabled, or
moltaro.secrets.retired codes. One invocation uses one immutable snapshot;
after provisioning or rotation, retry with a new invocation rather than looping
inside the old one. See the complete Managed secrets guide.
9. Create a custom Workspace UI page
Section titled “9. Create a custom Workspace UI page”Workspace UI is also API-first:
All routes in this section still use the same WORKSPACE_API_BASE_URL; they
are not PublicSite or portal endpoints.
- Inspect
GET /api/workspace/admin/ui-project/source-templatesor the page generators, then apply one to create a revision. - Make subsequent changes with
POST .../source-revisions/manual-edit. - Queue Check with
POST .../buildsandKind: 0; poll the build. - Queue Build with
Kind: 1; it creates an inactive immutable artifact. - Activate it with
POST .../artifacts/{artifactId}/activate.
The Workspace UI values deliberately differ from the C# project: Check = 0,
Build = 1, and Build does not activate automatically. See the complete
Workspace UI Project lifecycle.
Optional local IDE workflow
Section titled “Optional local IDE workflow”GET .../net-operation-project/download produces a ready-to-build ZIP for a
human working in a local IDE. It includes the generated workspace contract and
matching SDK files. It is transport convenience, not a requirement for an AI
agent and not an extra source of truth.