Source: docs/integration/errors.md

API errors

The Public API uses JSON errors. The OpenAPI contract is authoritative for the

status and shape of each route.

Most Public API routes return:

{
  "error": "Invalid API key",
  "code": "UNAUTHORIZED"
}

The HTTP channel returns a structured error object:

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid JSON body"
  }
}

Recovery guide

StatusTypical codesRecovery
400VALIDATION_ERROR, INVALID_CREDENTIAL, MANIFEST_INVALIDFix the request using the OpenAPI schema; do not retry unchanged input.
401UNAUTHORIZEDConfirm the API key and base URL belong to the same environment; ask the administrator to reissue the bundle if needed.
404CAPABILITY_NOT_FOUND, CREDENTIAL_NOT_FOUNDConfirm the identifier belongs to the current access bundle.
405METHOD_NOT_ALLOWEDUse the method documented for the route.
409CONFLICT, IDEMPOTENCY_KEY_REUSED, REVISION_CONFLICT, CAPABILITY_DISABLED, CREDENTIAL_NOT_CONFIGUREDRe-read the capability, use the current If-Match revision for an update or explicit state transition, and retry only after correcting the request.
502CAPABILITY_EXECUTION_UNAVAILABLE, UPSTREAM_*Inspect the bounded error body. Forgium never executes host-owned operations; UPSTREAM_* codes indicate endpoint or transport failure.
413REQUEST_TOO_LARGEReduce the credential request to the documented limit.
422VALIDATION_ERRORSend a text message with a non-empty body and valid fields.
500AGENT_RUNTIME_ERROR, INTERNAL_ERRORApply the host application's retry policy and retain the response code for support.
503CREDENTIAL_VAULT_UNAVAILABLE, POLICY_UNAVAILABLEDo not retry credential rotation repeatedly; retry other temporary service failures according to the host policy and contact the operator if they persist.

Never log API keys, endpoint tokens, authorization headers, or complete request

bodies containing secrets. For a suspected leak, stop and request rotation.

Capability runtime behavior

These are observable agent behaviors, not HTTP error codes. They describe how

the agent handles capability-related situations in conversation.

Missing arguments

When the user's message does not include a required argument for a capability,

the agent should ask for clarification rather than fabricating the value.

User: "Obtener las unidades funcionales."
Agent: "¿De qué consorcio querés consultar las unidades?"

The agent must not invent IDs, names, or other operational arguments to fill

missing fields.

No matching capability selected

When the user's request does not match any active capability (by topic, intent,

or available schema), the agent responds without calling a capability. This is

not an error — it is the expected behavior for out-of-scope or unsupported

requests.

User: "¿Cuál es la capital de Uruguay?"
Agent: "La capital de Uruguay es Montevideo."

If a model proposes a capability whose declared explicit exclusion matches the

request, the runtime also fails closed without contacting the endpoint. The

trace shows the selected candidate, an unresolved coverage_gap, and the

terminal safe_fallback; the exclusion cannot broaden authorization or

change account policy.

Capability execution failure

When the upstream endpoint returns an error (timeout, 5xx, unauthorized), the

agent communicates the unavailability without inventing data.

User: "Obtener las unidades del consorcio Torres del Agua."
Agent: "No pude consultar esa información en este momento. Por favor, intentá de nuevo."

The agent must not claim the consorcio does not exist, fabricate units, or

expose internal error codes to the user.

Host-owned operation result

Forgium does not approve or execute mutations. The host application owns

confirmation, authorization, concurrency, idempotency, and mutation. It may

report a terminal status through the operation-results endpoint after the host

operation finishes.

Empty result

When the capability returns a valid but empty result (e.g., a consorcio exists

but has no units), the agent reports the absence without treating it as an error.

User: "Obtener las unidades del consorcio Torres del Parque."
Agent: "No hay unidades registradas para Torres del Parque."

One capability per turn

The current runtime executes at most one capability per turn. This is a

platform limit, not an error. If a request needs another operation, only the

first matching capability is executed in the current turn. Structure the

conversation so each turn requests a single operation.

Current-run diagnostics

When present in a successful HTTP-channel response, capability_trace.events

uses stable statuses rather than model reasoning: not_selected, unresolved,

selected, arguments_invalid, execution_failed, empty_result,

result_received, response_generated, and runtime_failed. A

reason_code is a bounded technical category, not an explanation of why a

model made a decision. In particular, safe_fallback identifies the terminal

safe-response path, not its cause; inspect the preceding event. A

runtime_failed event distinguishes selection_inference_failed from

grounded_inference_failed.

The trace never includes prompts, chain-of-thought, message text, arguments,

result bodies, credentials, complete signed context values, headers, or stack

traces. It covers only the run returned by that response; use the opaque

run_id or benchmark_observation.correlation_id when contacting support.

See Current-run capability diagnostics

for the complete status, reason-code, selection, grounding, and diagnostic

semantics.