Submitting Intents

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

Documentation

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_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Federated 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"
  }
}
FieldRequiredDescription
schemaVersionYesMust be "1.0"
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
idempotency.clientRequestIdNoCaller-provided correlation key; enables lookup via GET /v1/intents?clientRequestId=xxx
idempotency.strategyNostrict (default), relaxed, or disabled
contextNoAgent reasoning context - stored permanently in the audit trail
context.sessionIdNoGroups 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:

StrategyBehavior
strictExact match required within window; any parameter difference is treated as a new intent
relaxedMinor parameter variations (whitespace, casing) are normalized before comparison
disabledNo 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 statusMeaningRecovery
400Parameter validation failedFix parameters per the issues array
401Invalid or revoked API keyCheck key status in the dashboard
403Intent denied by policyInspect denial.axisResults for per-axis reasoning
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