This guide implements a complete AgentChat integration for a fictional SaaS called SupportFlow. SupportFlow already has APIs for finding overdue invoices, sending reminders, and adding account notes. We will provision those APIs into AgentChat, create a user-scoped chat, start an asynchronous agent run, and render the result from durable messages and SupportFlow’s own database.
The important architectural boundary is concrete: AgentChat owns model reasoning, tool selection, chat history, and run control. SupportFlow continues to own customers, invoices, authorization, validation, and the final business records. API documentation connects the two systems.
You do not add every SaaS feature to the agent runtime. You expose a small set of core business operations as HTTP APIs and provision their contracts into each chat.
The finished request flow
- SupportFlow creates one AgentChat API key from the dashboard and stores it only on its backend.
- Its backend registers the SupportFlow operations with POST /api/api-documents.
- When a user opens the assistant, SupportFlow creates a session with the document UUID, an LLM configuration UUID, and write-only user credentials for its API host.
- SupportFlow sends the user message to POST /api/agent/sessions/{id}/chat.
- AgentChat reads the attached contract and uses its built-in http_request tool to call SupportFlow.
- SupportFlow polls AgentChat messages while its normal UI reads invoices and notes from the SupportFlow database.
Step 1: expose narrow business operations
The agent does not need database access or one enormous internal API. For this workflow, SupportFlow exposes exactly three tenant-aware endpoints:
GET /v1/invoices?status=overdue&limit=3
→ { "items": [{ "invoice_id": "inv_72", "account_id": "acct_9", "amount": 480, "currency": "USD", "due_at": "2026-08-01" }] }
POST /v1/reminders
{ "invoice_id": "inv_72", "tone": "friendly" }
→ { "reminder_id": "rem_31", "status": "queued" }
POST /v1/accounts/acct_9/notes
{ "body": "Friendly reminder queued for overdue invoice inv_72." }
→ { "note_id": "note_55", "created_at": "2026-08-23T09:30:00Z" } Each endpoint authenticates the caller, derives the tenant from the credential, and filters every database operation. IDs returned by one call become safe inputs to the next. The model never receives a database password or an unrestricted query interface.
Step 2: create the model configuration once
Every AgentChat session requires a user-owned LLM configuration. SupportFlow can create one through the dashboard or through the API and retain the returned UUID.
POST $AGENTCHAT_SITE_URL/api/llm-config
Authorization: Bearer ac_live_AGENTCHAT_KEY
Content-Type: application/json
{
"name": "Support production model",
"api_url": "https://llm-provider.example.com/v1/chat/completions",
"api_key": "provider_secret",
"model": "provider-model-name",
"max_context_length": 128000,
"max_output_tokens": 8192,
"temperature": 0.2,
"disable_reasoning": false
} The response is wrapped as success and data. Save data.id as the llm_config_id used when creating chats. AgentChat masks the provider key when configurations are read back.
Step 3: provision the SupportFlow API document
This is the plugin mechanism. The document contains operational instructions, exact inputs, exact outputs, and sequencing rules—not marketing copy and not a link that forces the agent to guess.
POST $AGENTCHAT_SITE_URL/api/api-documents
Authorization: Bearer ac_live_AGENTCHAT_KEY
Content-Type: application/json
{
"title": "SupportFlow Invoice Actions",
"description": "Find overdue invoices, queue reminders, and record account notes.",
"content": "# SupportFlow Invoice Actions\nBase URL: https://support.example.com/v1\n\nGET /invoices?status=overdue&limit=3 returns items with invoice_id, account_id, amount, currency, and due_at. Use only when the user requests invoice lookup.\n\nPOST /reminders body: invoice_id required; tone is friendly or firm. Response: reminder_id and status. Never send more reminders than the user requested.\n\nPOST /accounts/{account_id}/notes body: body required. Call only after the reminder request succeeds. Include the invoice ID and reminder status in the note.\n\nIf any write returns 401 or 403, stop writing and explain that the session credential needs access. Do not retry a permission denial."
} AgentChat returns the new document in data, including its UUID. Keep that UUID in SupportFlow’s integration configuration. Updating this document later changes the instructions used by subsequent chat turns because sessions attach the document rather than copying it.
Step 4: create a chat for the current SupportFlow user
POST $AGENTCHAT_SITE_URL/api/agent/sessions
Authorization: Bearer ac_live_AGENTCHAT_KEY
Content-Type: application/json
{
"title": "Invoice assistant for user_42",
"llm_config_id": "llm_config_uuid",
"api_document_ids": ["supportflow_document_uuid"],
"system_prompt": "Act only on the user’s explicit request. Summarize every write with the affected invoice and account IDs.",
"compact_threshold_percent": 80,
"max_turns": 12,
"tool_timeout_seconds": 120,
"tool_result_max_chars": 10000,
"host_headers": [
{ "host": "support.example.com", "header_key": "Authorization", "header_value": "Bearer short_lived_user_42_token" },
{ "host": "support.example.com", "header_key": "X-Workspace-ID", "header_value": "workspace_7" }
]
} Header values are write-only. AgentChat stores them for this session, injects them only when http_request targets the matching host, and does not expose their values to the model or API responses. A second SupportFlow user gets a different session with the same document UUID but different headers.
Step 5: start the asynchronous run
POST $AGENTCHAT_SITE_URL/api/agent/sessions/session_uuid/chat
Authorization: Bearer ac_live_AGENTCHAT_KEY
Content-Type: application/json
{ "message": "Find my three most overdue invoices, send each a friendly reminder, and add a note to each account." }
→ { "success": true, "data": { "session_id": "session_uuid", "state": "processing" } } AgentChat returns immediately and continues the run in the background. The agent receives the attached SupportFlow document plus exactly four built-in tools: get_api_document, http_request, sleep, and view_image. SupportFlow capabilities are not compiled into those tools; they are learned from the provisioned API contract and executed through http_request.
What the agent does during this request
- Call the documented overdue-invoice endpoint through http_request.
- Read the structured items and select at most the three invoices requested by the user.
- Queue reminders. Independent calls produced by one model response can execute concurrently.
- After successful reminder results are available, call the account-note endpoint with each returned invoice and account ID.
- Produce a final assistant message listing completed operations and any per-invoice failure.
This is why response design matters. A vague “success” result leaves the agent nothing reliable to connect to the next action. Structured IDs and statuses let the reasoning loop compose several ordinary APIs into one user outcome.
Step 6: poll durable messages, not an LLM stream
GET $AGENTCHAT_SITE_URL/api/agent/sessions/session_uuid/messages?after_id=&after_revision=0
Authorization: Bearer ac_live_AGENTCHAT_KEY
→ {
"success": true,
"data": {
"messages": [{ "id": "message_uuid", "role": "assistant", "content": "...", "stream_status": "streaming", "revision": 4 }],
"last_id": "message_uuid",
"last_revision": 4,
"is_processing": true,
"total_tokens": 2840
}
} SupportFlow polls once per second from its backend or proxied client, merges rows by message ID, and replaces content only when revision increases. AgentChat’s database is the source of truth for conversation output. SupportFlow’s database remains the source of truth for invoices, reminders, and notes.
When is_processing becomes false, SupportFlow can refresh its invoice and account queries. The normal product UI then shows the reminders and notes created through its own APIs; it does not need to parse the assistant’s prose to reconstruct business state.
Run control and failure recovery
GET /api/agent/sessions/session_uuid/state
POST /api/agent/sessions/session_uuid/stop
POST /api/agent/sessions/session_uuid/continue The state endpoint reports whether processing is active and whether the next action is continue. Stop requests cancel an active run. If a recoverable failure or max-turn limit pauses work, continue starts another run with a fresh turn budget and the same durable conversation context.
What to provision—and what not to provision
- Provision APIs that represent stable business capabilities: search, create, update, validate, publish, or inspect job status.
- Document required fields, constraints, response objects, error meanings, side effects, and ordering requirements.
- Attach only the documents needed for the chat experience instead of every internal endpoint.
- Keep credentials in host-specific session headers, never in prompts or API-document content.
- Do not expose raw SQL, unrestricted file access, or a generic internal proxy just to make the agent flexible.
- Let your own authorization and validation run on every tool request exactly as they do for other clients.
Why the capability surface can grow without growing the core tool set
A RAG product can provision search and citation endpoints. A story product can provision chapter, image-generation, and publishing endpoints. A coding product can provision workspace files, checks, and deployment endpoints. AgentChat still uses the same four core tools. The application-specific operations arrive as API documents, so adding a capability is a provisioning change rather than a new agent-runtime release.
That is the central AgentChat pattern: create API documents, create a scoped chat session, let the agent compose your HTTP operations, consume durable messages, and render the resulting records from your own application database.