Submitting Intents

Complete reference for the Formael Agent Plane — how to submit intents, handle responses, poll deferred results, and understand idempotency.

Documentation
4 of 8

Submitting Intents

The Agent Plane is the API surface your AI agents use to submit intents and retrieve results. All agent traffic flows through two endpoints.

Authentication

All Agent Plane requests require a platform-issued API key, scoped to a specific agent identity:

Authorization: Bearer fml_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

API keys are issued per agent from the Formael dashboard under Agents → API Keys. Each key inherits the permission scope of the agent it belongs to.


POST /agent/v1/intents

Submit an intent for policy evaluation and execution.

Request body

{
  "domain": "document-signing",
  "action": "create",
  "entity": "contract",
  "parameters": {
    "signerName": "Jane Smith",
    "signerEmail": "[email protected]",
    "templateId": "tmpl_mutual_nda"
  },
  "context": {
    "agentGoal": "string — the agent's current goal",
    "reasoning": "string — why the agent is taking this action",
    "confidence": 0.95,
    "alternativesConsidered": ["sent email instead", "scheduled meeting"]
  }
}
FieldRequiredDescription
domainYesThe capability domain (e.g., document-signing)
actionYesThe action to take (e.g., create)
entityYesThe entity being acted on (e.g., contract)
parametersYesValidated against the capability's parameter schema
contextNoAgent reasoning context — stored in the audit trail

The (domain, action, entity) tuple must match a capability available to your organization. Use the Capability Discovery API to find what's available.

The context field

The context field is optional but strongly recommended. It is stored permanently in the audit record and becomes part of the Reasoning Trace — the answer to "why did the agent take this action?" It is visible to human approvers during HITL review and to compliance teams querying audit history.

Structured context significantly improves the value of the audit trail and the quality of human-in-the-loop decisions.

Responses

200 OK — Executed

The intent was approved and executed synchronously:

{
  "iecId": "01HX4K2M9V3T7P8Q5N6R0J1W2Y",
  "outcome": "executed",
  "state": "SUCCEEDED",
  "result": {
    "contractId": "env_2XmZ9kPq...",
    "status": "sent"
  },
  "executedAt": "2024-01-15T12:00:00Z",
  "latencyMs": 843
}

202 Accepted — Deferred

The intent requires human approval. Execution is paused:

{
  "iecId": "01HX4K2M9V3T7P8Q5N6R0J1W2Y",
  "outcome": "deferred",
  "state": "PENDING_APPROVAL",
  "approvalChannel": "dashboard",
  "estimatedResolution": "2024-01-15T14:30:00Z"
}

Your agent should store the iecId and poll GET /agent/v1/intents/:iecId to check for resolution.

403 Forbidden — Denied

The intent was denied by the policy engine:

{
  "iecId": "01HX4K2M9V3T7P8Q5N6R0J1W2Y",
  "outcome": "denied",
  "state": "CLOSED",
  "denial": {
    "axis": "semantic",
    "reason": "Intent parameters match a blocked keyword pattern",
    "ruleId": "rule_8Xk2P..."
  }
}

The denial.axis field tells your agent which policy axis blocked the action. The denial.reason provides human-readable context for understanding why.

200 OK — Deduplicated

An identical intent was executed recently and the cached result is returned:

{
  "iecId": "01HX4K2M9V3T7P8Q5N6R0J1W2Y",
  "outcome": "deduplicated",
  "originalIecId": "01HX4K2M9V3T7P8Q4M5R0J1W2Z",
  "result": { ... }
}

The deduplication is recorded in the audit trail. The original IEC ID is returned for traceability.

400 Bad Request — Validation error

The request body was malformed or the parameters did not validate against the capability schema:

{
  "error": "VALIDATION_ERROR",
  "message": "Parameter validation failed",
  "issues": [
    {
      "field": "parameters.signerEmail",
      "message": "Expected a valid email address"
    }
  ]
}

GET /agent/v1/intents/:iecId

Poll the status of a specific IEC, typically used for deferred intents awaiting human approval.

curl https://api.formael.com/agent/v1/intents/01HX4K2M9V3T7P8Q5N6R0J1W2Y \
  -H "Authorization: Bearer YOUR_API_KEY"

Response

While pending:

{
  "iecId": "01HX4K2M9V3T7P8Q5N6R0J1W2Y",
  "outcome": "deferred",
  "state": "PENDING_APPROVAL"
}

After approval and execution:

{
  "iecId": "01HX4K2M9V3T7P8Q5N6R0J1W2Y",
  "outcome": "executed",
  "state": "SUCCEEDED",
  "result": { ... },
  "executedAt": "2024-01-15T14:28:47Z"
}

After denial:

{
  "iecId": "01HX4K2M9V3T7P8Q5N6R0J1W2Y",
  "outcome": "denied",
  "state": "CLOSED",
  "denial": {
    "axis": "identity",
    "reason": "Approver denied the request",
    "approverComment": "Outside vendor scope for this quarter"
  }
}

Polling guidance

Formael does not impose a polling rate limit on the intent status endpoint. A reasonable polling interval for most workflows is 5–30 seconds. For time-sensitive approvals, 5 seconds is appropriate. Reduce polling frequency if the estimatedResolution from the deferral response is hours away.


Idempotency

Formael automatically deduplicates intents within a configurable time window. The platform generates a semantic fingerprint by combining:

  • Your organization and agent identity
  • The capability tuple (domain, action, entity)
  • A normalized representation of the parameters

If an identical intent was successfully executed within the deduplication window, the platform returns the cached result instead of executing again. The agent receives the same response shape as a successful execution, with outcome: "deduplicated" and a reference to the original IEC.

You do not need to manage idempotency keys. The platform handles this automatically.

The deduplication window is configurable per capability in your organization settings. Defaults:

Capability typeDefault window
Reversible actions (e.g., create ticket)60 seconds
Irreversible actions (e.g., send contract)24 hours

Error handling

HTTP statusMeaningRecovery
400Parameter validation failedFix parameters per the issues array
401Invalid or revoked API keyCheck key status in the dashboard
403Intent denied by policyInspect denial.axis and denial.reason
404Capability not foundVerify (domain, action, entity) via capability discovery
409Capability not configured for your organizationSet up a provider binding in the dashboard
429Rate limit exceededRespect the Retry-After header
5xxPlatform errorRetry with exponential backoff; IEC state is preserved

For 5xx errors, the IEC record was created before the failure. The iecId in the error response (when present) can be used to poll for recovery status.