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_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxAPI 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"]
}
}| Field | Required | Description |
|---|---|---|
domain | Yes | The capability domain (e.g., document-signing) |
action | Yes | The action to take (e.g., create) |
entity | Yes | The entity being acted on (e.g., contract) |
parameters | Yes | Validated against the capability's parameter schema |
context | No | Agent 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 type | Default window |
|---|---|
| Reversible actions (e.g., create ticket) | 60 seconds |
| Irreversible actions (e.g., send contract) | 24 hours |
Error handling
| HTTP status | Meaning | Recovery |
|---|---|---|
400 | Parameter validation failed | Fix parameters per the issues array |
401 | Invalid or revoked API key | Check key status in the dashboard |
403 | Intent denied by policy | Inspect denial.axis and denial.reason |
404 | Capability not found | Verify (domain, action, entity) via capability discovery |
409 | Capability not configured for your organization | Set up a provider binding in the dashboard |
429 | Rate limit exceeded | Respect the Retry-After header |
5xx | Platform error | Retry 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.