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 credential bound to a specific agent identity. Formael supports two authentication methods:
API key binding - a platform-issued key scoped to a registered agent:
Authorization: Bearer fml_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxFederated JWT - a token issued by your enterprise identity provider (Okta, Azure AD, Auth0), validated against a registered Identity Federation:
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...See Agent Authentication for the full authentication model, credential bindings, and federated identity setup.
POST /v1/intents
Submit an intent for policy evaluation and execution.
Request body
The request body follows the IntentEnvelope v1 schema. The full JSON Schema is published at GET /agent/v1/schema/intent-envelope (no auth required).
{
"schemaVersion": "1.0",
"domain": "document-signing",
"action": "create",
"entity": "contract",
"parameters": {
"signerName": "Jane Smith",
"signerEmail": "[email protected]",
"templateId": "tmpl_mutual_nda"
},
"idempotency": {
"clientRequestId": "req_abc123",
"strategy": "strict"
},
"context": {
"agentGoal": "Initiate NDA for new vendor partnership",
"taskContext": "Preparing for technical due diligence meeting",
"decisionChain": ["Partnership requires NDA before sharing specs"],
"confidence": 0.95,
"alternativesConsidered": ["Sent email request instead"],
"sessionId": "session_vendor_onboarding_jan15"
}
}| Field | Required | Description |
|---|---|---|
schemaVersion | Yes | Must be "1.0" |
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 |
idempotency.clientRequestId | No | Caller-provided correlation key; enables lookup via GET /v1/intents?clientRequestId=xxx |
idempotency.strategy | No | strict (default), relaxed, or disabled |
context | No | Agent reasoning context - stored permanently in the audit trail |
context.sessionId | No | Groups this IEC with others in the same agent session |
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.
Responses
200 OK - Executed
The intent was approved and executed synchronously:
{
"iecId": "01HX4K2M9V3T7P8Q5N6R0J1W2Y",
"schemaVersion": "1.0",
"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",
"schemaVersion": "1.0",
"outcome": "deferred",
"state": "PENDING_APPROVAL",
"estimatedResolution": "2024-01-15T14:30:00Z"
}Your agent should store the iecId and poll GET /v1/intents/:iecId to check for resolution.
403 Forbidden - Denied
The intent was denied by the policy engine:
{
"iecId": "01HX4K2M9V3T7P8Q5N6R0J1W2Y",
"schemaVersion": "1.0",
"outcome": "denied",
"state": "CLOSED",
"denial": {
"axisResults": {
"semantic": {
"verdict": "DENIED",
"reason": "Intent parameters match a blocked keyword pattern",
"ruleId": "rule_8Xk2P..."
}
}
}
}The per-axis results tell your agent exactly which policy axis blocked the action and why.
200 OK - Deduplicated
An identical intent was executed recently and the cached result is returned:
{
"iecId": "01HX4K2M9V3T7P8Q5N6R0J1W2Y",
"outcome": "deduplicated",
"originalIecId": "01HX4K2M9V3T7P8Q4M5R0J1W2Z",
"result": { "..." }
}400 Bad Request - Validation error
{
"error": "VALIDATION_ERROR",
"message": "Parameter validation failed",
"issues": [
{
"field": "parameters.signerEmail",
"message": "Expected a valid email address"
}
]
}GET /v1/intents/:iecId
Poll the status of a specific IEC, typically used for deferred intents awaiting human approval.
curl https://api.formael.com/v1/intents/01HX4K2M9V3T7P8Q5N6R0J1W2Y \
-H "Authorization: Bearer YOUR_API_KEY"Polling guidance: a reasonable interval is 5–30 seconds. Reduce frequency if the estimatedResolution is hours away.
GET /v1/intents?clientRequestId=xxx
Look up an IEC by your caller-provided correlation key:
curl "https://api.formael.com/v1/intents?clientRequestId=req_abc123" \
-H "Authorization: Bearer YOUR_API_KEY"Useful for checking whether a previous submission succeeded before retrying. Returns the IEC record if found.
Idempotency
Formael automatically deduplicates intents within a configurable window using a semantic fingerprint of (organizationId + agentId + domain + action + entity + normalized parameters).
idempotency.strategy values:
| Strategy | Behavior |
|---|---|
strict | Exact match required within window; any parameter difference is treated as a new intent |
relaxed | Minor parameter variations (whitespace, casing) are normalized before comparison |
disabled | No deduplication; every submission executes independently |
You do not need to manage idempotency keys. The platform handles deduplication automatically based on content.
If you want to retrieve an existing IEC by your own reference, use clientRequestId rather than relying on deduplication.
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.axisResults for per-axis reasoning |
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 |