Integrate AI agents with Forgeplane
An external AI agent can use Forgeplane to discover delivery resources, request a governed run, and observe its result. The safe integration boundary is the documented HTTP API. The agent should not scrape the web UI, invent request fields, handle raw infrastructure credentials, or make its own approval decisions.
This guide is framework-independent. It applies to coding agents, operations agents, LLM tool callers, and custom automation that can call HTTPS endpoints and parse JSON.
Choose an API access path
Section titled “Choose an API access path”Forgeplane offers four ways to discover or reach product resources. Use the path that matches the caller:
| Access path | Entry point | Best for | Boundary |
|---|---|---|---|
| LLM documentation index | llms.txt | A fetch-based agent discovering the official API, authentication, permissions, and workflow documentation | It is a curated public-documentation index, not a live coordinator endpoint list or an authorization contract. |
| Interactive API documentation | /api/docs |
A human operator or browser-capable agent browsing declared methods, request fields, responses, and status codes on the running coordinator | An agent may inspect it in read-only mode without a key. Only an authorized human should enter a personal key and use Try it out; the page keeps that key in the page only and clears it on reload. |
| Direct HTTP API | /api/v1 |
AI agents, scripts, and application integrations using a standard HTTP client such as curl or a language HTTP library |
Send JSON and X-API-Key only to an allowlisted host, method, and route. This is the supported automation boundary. |
| Browser UI | /catalog, /projects, /environments, and /workloads/runs |
Human review, resource selection, approval, and operational investigation | Use a Forgeplane browser session. The browser UI is a human interface, not an agent API contract. |
A browser-capable agent can open /api/docs in read-only mode to browse the interactive API documentation declared by the target coordinator. Do not give that browser agent a credential or let it use Try it out unless the operator explicitly authorizes the exact call. A fetch-only agent should start with Forgeplane llms.txt, follow the narrow documentation links needed for its task, and avoid scraping the JavaScript-rendered interactive page or the browser UI.
For live resource browsing, configure a narrow direct-HTTP allowlist and let the agent call reviewed GET /api/v1 routes. Use mutations only after the explicit authorization required by the default agent policy below.
Before authentication, GET /api/v1/system/identity and GET /api/v1/system/version identify the running coordinator and its API version. After authentication, use GET /api/v1/auth/whoami and current resource responses as runtime evidence. See the Coordinator API reference for the resource directory, access options, correlation headers, request limits, and error behavior.
Do not infer a route or field from an older client, another Forgeplane release, or an example on this page. Review the target coordinator’s interactive docs together with this website’s current behavior and permissions guidance before changing the agent’s allowlist. The actual server response remains authoritative. Fail closed when a response, field, status, or authorization result is outside the reviewed behavior.
Default agent policy
Section titled “Default agent policy”Use this policy as the starting boundary for an agent integration:
ALLOW BY DEFAULT- Inspect the authenticated identity and permission decisions.- Read projects, environments, templates, versions, runs, and logs within the assigned scope.- Request one run after its exact target, operation, template version, and inputs are confirmed.- Observe the returned run ID until a known terminal result or the operator's deadline.
REQUIRE EXPLICIT OPERATOR AUTHORIZATION- Create a run.- Cancel or requeue a run.- Change a project, environment, template, credential, policy, or feature gate.
DENY BY DEFAULT- Approve or reject a run.- Delete records.- Use browser cookies or UI-only routes.- Copy credentials or secret values into prompts, logs, artifacts, or model-visible context.- Retry a mutation after an ambiguous result unless that operation documents safe retry behavior.These are integration defaults, not a substitute for Forgeplane authorization. The coordinator still evaluates platform permissions, organization membership, team scope, resource ownership, lifecycle state, feature gates, quotas, and approval policy.
Create a least-privilege identity
Section titled “Create a least-privilege identity”Use a user-owned requester service account for routine runs whose internal execution plan is already cached. The owner user supplies the user-level audit attribution required by the template-run endpoint and must have the necessary organization and team access. A requester can read delivery resources and execute a cached plan, but cannot approve, cancel, or materialize a missing internal execution plan. Do not reuse a human administrator’s credential.
Before requester automation uses a new plan identity, an authorized maintainer must create the first run for the exact project, template version, and operation. That first run materializes the internal execution plan. Its cache identity also includes the current compiler version and compiled graph, so a product or graph change can require materialization again. A requester can reuse the cached plan afterward. If automation itself must create the first run, it needs a user-owned maintainer account with broader assembly:write and approval authority; keep approval endpoints out of that agent’s tool set and disclose the broader authority.
In the current release, a team-owned service account cannot derive the user-level created_by required for template-run creation. Use a team-owned account only for operations that do not require that attribution. Do not work around this limit by sending an arbitrary user UUID.
Store the API key in the agent runtime’s secret store and inject it only into the HTTP client process. Do not put an API key in a prompt, command argument recorded by the agent, generated report, repository file, or conversation transcript. Do not give the model a tool that can print its environment.
Send the key through the documented header:
X-API-Key: <service-account-api-key>A valid key does not widen its owner’s team or resource scope. Review Permissions and roles before assigning a broader role.
Permission baseline
Section titled “Permission baseline”The normal read-and-run integration uses these layered checks. Platform permission and team action must both pass where shown. Resource, lifecycle, and feature-gate checks still apply.
| Agent action | API operation | Required authorization |
|---|---|---|
| Inspect identity | GET /api/v1/auth/whoami |
Authenticated principal |
| Test authorization | POST /api/v1/auth/can-i |
Authenticated principal |
| List projects | GET /api/v1/projects?team_id={team_id} |
project:read with team.metadata.read |
| List environments | GET /api/v1/environments?team_id={team_id} |
environment:read with team.metadata.read |
| Read templates and versions | GET /api/v1/registry/templates |
registry:read |
| Admit a template run for the environment | POST /api/v1/registry/templates/{id}/run |
run:create with team.secret.read |
| Execute an already cached internal plan | Same run request | assembly:run with team.metadata.read |
| Materialize a missing internal plan | First run for that plan identity | assembly:write with team.metadata.write |
| Read a run and its persisted logs | GET /api/v1/runs/{id} and /logs |
run:read with team.secret.read |
| Cancel an eligible run | POST /api/v1/runs/{id}/cancel |
run:cancel with team.secret.read |
| Requeue an eligible run | POST /api/v1/runs/{id}/requeue |
run:create with team.secret.read |
The requester role has run:create and assembly:run, but not assembly:write. A missing internal plan therefore returns 403 for a requester until a maintainer has materialized that exact plan identity.
Do not treat can-i as a reservation or an authorization bypass. It is a preflight decision. The actual operation can still fail because state, scope, policy, quota, or another resource changed.
1. Verify identity and access
Section titled “1. Verify identity and access”First, verify which principal the HTTP client uses:
curl --fail-with-body --silent --show-error \ "$FORGEPLANE_URL/api/v1/auth/whoami" \ -H "Accept: application/json" \ -H "X-API-Key: $FORGEPLANE_API_KEY"The review envelope accepts only resource_attributes. Each review evaluates
the authenticated User or service account; it cannot select another subject.
Check the Team-scoped run-creation capability:
{ "resource_attributes": { "group": "forgeplane.io", "version": "v1", "resource": "runs", "verb": "create", "team_id": "22222222-2222-2222-2222-222222222222" }}This collection review does not prove that an internal execution plan exists or that the caller can materialize it. Keep the maintainer-first workflow above; the actual run operation enforces those additional requirements.
Send the JSON object to POST /api/v1/auth/can-i. An allowed review returns HTTP 200:
{ "status": { "allowed": true, "denied": false, "reason": { "code": "allowed", "message": "authorization granted" } }}Proceed only when status.allowed is true. A denial has
status.denied: true. Both booleans false means an indeterminate
evaluation_error; stop rather than treating it as permission to proceed.
See the review contract
for the safe result codes and validation rules.
After resolving IDs, use named projects/get, environments/get, or
runs/get reviews with name and the matching team_id. A separately
authorized cancellation can review runs/cancel. A runs/create review
does not replace a requeue operation’s lifecycle checks. Do not expose cancel
or requeue to the default requester tool set.
Stop if the identity is unexpected or status.allowed is false. Fix the narrow missing role, membership, or scope instead of granting general administrative access.
2. Resolve resource IDs from the API
Section titled “2. Resolve resource IDs from the API”Resolve the target from authenticated API responses. Do not assume that display names are unique, and do not copy stale IDs from an old trace.
- Call
GET /api/v1/projects?team_id={team_id}and select the intended project UUID. - Call
GET /api/v1/environments?team_id={team_id}and verify that the returned environment belongs to that project. - Call
GET /api/v1/registry/templatesand select the intended template UUID. - Call
GET /api/v1/registry/templates/{id}/versionsorGET /api/v1/registry/templates/{id}/versions/{version}. - Read the base
source_url,tool_type, and default worker pool from the template entry, then read the selected version’sgit_ref,schema, andvariables. - Build the effective execution projection before authorization.
TemplateVersion.variables can override the base source URL, Git ref, path, tool type, and input schema. Apply the runtime precedence exactly:
source_url,git_url,repo_url, orrepositoryinvariablesoverride the template entry’ssource_url; conflicting non-empty URL aliases are invalid;- the first non-empty
git_ref,ref, orrevisioninvariablesoverrides the version’s top-levelgit_ref; an empty effective ref defaults tomain; variables.pathoverrides the default empty path by presence;- the first non-empty
tool_typeortoolinvariablesoverrides the template entry’stool_type; and variables.input_schema, thenvariables.schema, overrides the version’s top-levelschema.
Validate the effective source URL, Git ref, path, tool type, and schema as one projection. Require the effective Git ref to be a reviewed immutable commit SHA; validating only the top-level git_ref is unsafe because an override can select different code. Validate non-secret inputs against the effective schema and show the whole resolved projection to the operator. If the agent cannot reproduce this precedence, fail closed whenever a reserved projection override is present and ask an operator to normalize the template version.
Use the returned UUIDs as identifiers. Use names only for confirmation messages shown to the operator.
3. Request one governed run
Section titled “3. Request one governed run”The template-run request requires environment_id and operation. A typical Terraform or OpenTofu plan request is:
{ "environment_id": "11111111-1111-1111-1111-111111111111", "operation": "plan", "version": "1.2.3", "inputs": { "region": "eu-central-1" }}Send the request to POST /api/v1/registry/templates/{id}/run:
curl --fail-with-body --silent --show-error \ -X POST \ "$FORGEPLANE_URL/api/v1/registry/templates/$TEMPLATE_ID/run" \ -H "Accept: application/json" \ -H "Content-Type: application/json" \ -H "X-API-Key: $FORGEPLANE_API_KEY" \ --data-binary @run-request.jsonApply these rules before sending it:
- Use an operation supported by the selected tool and release. Ansible uses
execute; Terraform and OpenTofu use their documented run operations. - Before a requester submits, confirm that an authorized maintainer has already created the first run for this project, template version, operation, compiler version, and compiled graph. A new identity needs materialization again; do not retry a requester’s
403as though it were transient. - Validate
inputsagainst the effective schema after applying the documented version-variable precedence. See Input schema. Do not place secret values in ordinary inputs when Forgeplane’s secret mechanism should supply them. - Omit
requested_worker_pool_nameunless the operator intentionally requests a pool. If provided, it must match the template’s configured default pool; it cannot replace that default. - Let the authenticated user-owned service account establish audit identity through its owner user. Omit
created_by; do not supply it as a way to impersonate another actor. Stop instead of submitting a run through a team-owned service account. - Show the resolved project, environment, template, version, effective source URL, Git ref, path, tool type, schema, operation, and non-secret inputs to the operator before mutation.
For Ansible-specific inventory, secret-slot, host-key, structured-output, and worker requirements, follow Ansible execution.
The coordinator returns the accepted run, including its id. A 202 Accepted response does not mean that the run succeeded. Persist the returned run ID and the coordinator’s X-Request-ID and X-Support-ID response headers before observing the run.
4. Observe the exact run
Section titled “4. Observe the exact run”Use the run ID returned by the create request. Do not search by name and assume the newest result is the one the agent created.
| Purpose | Operation |
|---|---|
| Read current run state | GET /api/v1/runs/{id} |
| Read persisted log entries | GET /api/v1/runs/{id}/logs |
| UI-oriented log stream | GET /api/v1/runs/{id}/logs/stream |
For a generic machine integration, poll GET /api/v1/runs/{id} and read persisted JSON logs from GET /api/v1/runs/{id}/logs. In the current release, pending_approval is a valid nonterminal run status. Treat queued, pending_approval, running, and canceling as known nonterminal states. The known terminal states are succeeded, failed, canceled, and timed_out.
The SSE endpoint is UI-oriented. Its response has no documented machine event-payload or reconnect contract, and runtime component events can contain HTML. Do not use it as a generic machine-readable log protocol. A purpose-built client can consume it only when it is coupled to and tested against the exact runtime implementation.
Use bounded observation:
- stop when the run reaches a known terminal result;
- stop at the operator’s configured observation deadline;
- report the run ID, last known status, and correlation identifiers when observation ends; and
- fail closed on an unknown status instead of treating it as success.
A successful HTTP read is not evidence that infrastructure execution succeeded. The run’s terminal state and evidence are the result.
Cancellation and requeue are separate mutations
Section titled “Cancellation and requeue are separate mutations”The advanced endpoints are POST /api/v1/runs/{id}/cancel and POST /api/v1/runs/{id}/requeue. Keep them out of the requester’s default tool set.
Cancellation is allowed when the run is queued, pending_approval, running, or canceling. A queued or pending run becomes canceled with 200. A running run becomes canceling with 202; keep polling the same run ID until it reaches a terminal status, because the worker stops the tool and reports the outcome first.
Requeue is limited to eligible failed, canceled, or timed_out runs. It mutates the existing run back to queued; it does not create a new run. The same run ID remains authoritative, so continue polling that ID. Requeue clears prior execution result fields while preserving the original intent and execution snapshot. Capture evidence that must remain separately accessible before requeueing.
Require explicit operator authorization for either action. Do not automatically retry a mutation after a timeout, connection loss, or other ambiguous response. First read the authoritative run state and follow any idempotency behavior declared for that exact operation.
Keep approval human-controlled
Section titled “Keep approval human-controlled”The default agent identity must not approve or reject a run. Treat approval as an external human decision boundary, not as another step the requesting model can satisfy.
Use separate principals for request and review. A requester submits the execution intent. An authorized reviewer inspects the exact run, evidence, reason, pending-run identity, and irreversible-impact acknowledgement through the governed approval workflow. The agent can report that review is required, but it must not decide that its own request is safe.
This guide deliberately provides no approval-mutation recipe. If you build a separate operator integration, use only the reviewed approval endpoint on the target coordinator, keep run:approve out of the requester identity, and follow Approval workflows.
Handle failures without guessing
Section titled “Handle failures without guessing”Forgeplane errors generally use {"error":"message"}. Preserve the actual HTTP response and correlation headers, then apply these defaults:
| Status | Agent behavior |
|---|---|
400 |
Correct the request against the runtime schema. Do not drop rejected fields silently. |
401 |
Stop. The credential is missing, invalid, or expired. |
403 |
Stop. Inspect permission, membership, scope, lifecycle, feature gate, and approval state. |
404 |
Re-resolve the resource in the authenticated scope. Do not substitute a same-named object. |
409 |
Read current state and present the conflict. Do not overwrite it. |
422 |
Treat the operation-specific validation result as a failed precondition. |
429 |
Respect Retry-After and the operation’s retry safety. |
500 or 503 |
Record correlation identifiers and stop the mutation path unless the exact contract makes retry safe. |
X-Client-Request-ID helps correlate client logs. It is not an idempotency key. Use Idempotency-Key only on operations that explicitly declare it.
Copy-ready instruction block
Section titled “Copy-ready instruction block”Give an integrating agent this short instruction after an operator has reviewed /api/docs on the target coordinator and configured its direct HTTP allowlist:
Use only the reviewed Forgeplane /api/v1 methods and routes in your HTTP-tool allowlist. Do not scrape the interactive API docs or browser UI, and do not invent request fields. Use the permissions reference, self-subject resource_attributes reviews, and the actual operation for authorization.Authenticate with the injected service-account API key, but never print, return, store, or place it in model-visible context.Before a run request, call whoami; resolve all UUIDs from current API responses; review the required resource and verb with matching name and team_id where applicable, proceeding only when status.allowed is true; build and validate the effective template projection after reserved variable overrides; confirm its effective Git ref is an immutable commit; confirm a maintainer has materialized this exact execution-plan identity; validate non-secret inputs against the effective schema; and show the resolved intent for operator authorization.Submit at most one mutation for that authorization. A 202 response is acceptance, not success. Persist the returned run ID and correlation headers, then poll that exact ID and read its persisted JSON logs. Do not treat the UI-oriented SSE stream as a generic machine protocol.Do not approve, reject, cancel, requeue, delete, or modify configuration unless the operator explicitly authorizes that separate action.Do not infer success from HTTP status, cancellation from process termination, or safety from the agent's own judgment. Fail closed on unknown fields, states, routes, or ambiguous mutation results.Integration checklist
Section titled “Integration checklist”- Confirm the target coordinator with
GET /api/v1/system/identityandGET /api/v1/system/version. - Have an operator review
/api/docs, then allowlist only the required direct/api/v1host, methods, routes, and fields. - Use a user-owned requester service account only for cached-plan runs; do not invent
created_byfor a team-owned account. - Have an authorized maintainer create the first run for each new project, template-version, operation, compiler, and graph identity.
- Keep the API key outside prompts, logs, and repository files.
- Limit the HTTP tool to the required host, methods, and routes.
- Verify identity and all combined permission, team-action, and team-ID checks before mutation.
- Resolve current UUIDs and validate the effective source URL, Git ref, path, tool type, and schema after reserved version-variable overrides.
- Require operator authorization for the resolved run intent.
- Persist the returned run ID and correlation headers.
- Observe that exact run and report unknown states as errors.
- Keep approval, cancellation, requeue, deletion, and configuration changes outside the default agent authority.
For the underlying product model, read Run operations, Service accounts, Permissions and roles, and the Coordinator API reference.