Appearance
Dedicated Agent
A per-user, always-on agent with its own gateway, available to accounts with the dedicated_agent flag. Chat with it, inspect its activity, manage its scheduled jobs and autonomous runs, and replay its console history.
Endpoints
| Method | Path | Purpose |
|---|---|---|
| POST | /microservices/dedicated-agent/chat/stream | Send a message (streamed reply over the socket) |
| POST | /microservices/dedicated-agent/chat/ | Send a message (synchronous) |
| GET | /microservices/dedicated-agent/messages/ | Console history |
| GET | /microservices/dedicated-agent/activity/ | Activity log and spend |
| POST | /microservices/dedicated-agent/kill/ | Pause the agent |
| GET | /microservices/dedicated-agent/jobs/ | Scheduled jobs |
| GET | /microservices/dedicated-agent/jobs/{job_id}/ | One job |
| DELETE | /microservices/dedicated-agent/jobs/{job_id}/ | Delete a job |
| POST | /microservices/dedicated-agent/jobs/{job_id}/{action}/ | Pause, resume or run a job now |
| POST | /microservices/dedicated-agent/runs/ | Start an autonomous run |
| GET | /microservices/dedicated-agent/runs/{run_id}/ | Run status |
| GET | /microservices/dedicated-agent/runs/{run_id}/events/ | Run event stream |
| POST | /microservices/dedicated-agent/runs/{run_id}/{action}/ | Approve a tool call, or stop the run |
POST /microservices/dedicated-agent/chat/stream
Send a message (streamed reply over the socket)
Starts a turn on your dedicated agent and returns immediately with 202. The agent's progress and answer arrive on the WebSocket ws/dedicated-agent/{agent_id}/ (same stage:* telemetry envelope as Chat AI — see Streaming & WebSockets), tagged with the conversation's chat_session_id, and the answer is also persisted to that conversation, so it survives a closed tab.
Conversations run in parallel. Each conversation takes one turn at a time, and the agent works on up to 10 conversations at once (the operator can change the limit). A second message to a busy conversation, or any message while the agent is at its limit, answers 409 and nothing is sent.
A turn is prepared like a Chat AI turn: the same skill, thinking level, attachment and database fields, with the same ownership checks. The skill and the thinking level are sticky per conversation — send them when they change, not on every turn. Your saved SSH machines are available to the agent automatically.
Auth: Session token · In the app: Dedicated Agent console; Chat AI with the Dedicated agent selected
Request body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
message | string | yes | |
chat_session_id | integer | no | The conversation: a sessions/ row of type dedicated-agent you own. Omitted: the agent's default conversation. |
reasoning_effort | string ("minimal", "low", "medium", "high", "xhigh", "none") | no | Thinking level. Sticky for the conversation; an unknown value is ignored. Unset means your saved default, else medium. Quick, Balanced and Deep in the app choose the model as well as the effort. |
active_skill | string | no | Skill to run in, sticky for the conversation. An empty string clears it; an unknown skill answers 404. |
attached_files | object[] | no | Files from My Data, as in Chat AI. Replaces the previous attachment set; files you may not use answer 400. |
database_tables | object[] | no | Tables to query, as in Chat AI. Replaces the previous set; an empty list detaches all. |
json
{
"message": "Draft a reply to the supplier about the late delivery.",
"chat_session_id": 9310,
"reasoning_effort": "high",
"active_skill": "supplier-correspondence"
}Response 202 — Turn started; listen on the socket.
| Field | Type | Description |
|---|---|---|
status | string ("started") | |
chat_session_id | integer | |
session_id | string, nullable | The gateway's id for this conversation. |
reasoning_effort | string | The effort this turn runs at. |
model | string, nullable | The model this turn runs on. |
active_skill | string, nullable |
json
{
"status": "started",
"chat_session_id": 9310,
"session_id": "console-ag_4f2a-9310",
"reasoning_effort": "high",
"model": "main",
"active_skill": "supplier-correspondence"
}Response 400 — message missing, bad chat_session_id, or an attachment or table you may not use.
json
{
"detail": "Authentication credentials were not provided."
}Response 403 — chat_session_id is not one of your dedicated-agent conversations.
Response 404 — You have no dedicated agent, or active_skill names no skill.
json
{
"detail": "no dedicated agent for this user"
}Response 409 — The agent is not running, this conversation already has a turn in progress, or the agent is at its concurrent-turn limit.
json
{
"detail": "this conversation already has a turn in progress",
"busy_chat_session_id": 9310
}Errors
| Status | Body | When |
|---|---|---|
409 | {"detail":"this conversation already has a turn in progress","busy_chat_session_id":9310} | A turn is still running in this conversation. Wait for its answer. |
409 | {"detail":"agent is at its concurrent-turn limit (10)","busy_chat_session_ids":[9302,9310],"max_concurrent_turns":10} | The agent is already working in as many conversations as it may. |
409 | {"detail":"agent is paused"} | The agent is not running. |
Example
bash
curl -X POST "https://api.example.com/microservices/dedicated-agent/chat/stream" \
-H "Authorization: Token $FINBLADE_TOKEN" \
-H "Content-Type: application/json" \
-d '{"message":"Draft a reply to the supplier about the late delivery.","chat_session_id":9310,"reasoning_effort":"high","active_skill":"supplier-correspondence"}'POST /microservices/dedicated-agent/chat/
Send a message (synchronous)
Waits for the agent's answer (up to 5 minutes) and returns it, in the agent's default conversation. Takes the same turn fields as the streaming endpoint (reasoning_effort, active_skill, attached_files, database_tables) and answers the same 409s. Prefer the streaming endpoint from interactive clients, and for any conversation other than the default one.
Auth: Session token
Request body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
message | string | yes | |
reasoning_effort | string ("minimal", "low", "medium", "high", "xhigh", "none") | no | |
active_skill | string | no | |
attached_files | object[] | no | |
database_tables | object[] | no |
Response 200 — The answer, plus the ids of anything the turn built (for example mgid for a dashboard chart).
| Field | Type | Description |
|---|---|---|
answer | string | |
session_id | string, nullable | |
generated_files_urls | string[] | |
reasoning_effort | string |
Response 404 — No dedicated agent, or unknown skill.
Response 409 — Agent not running, busy in the default conversation, or at its concurrent-turn limit.
Response 502 — Gateway error.
Response 503 — Agent unreachable (it may be restarting).
Example
bash
curl -X POST "https://api.example.com/microservices/dedicated-agent/chat/" \
-H "Authorization: Token $FINBLADE_TOKEN"GET /microservices/dedicated-agent/messages/
Console history
The agent's default conversation (oldest first within the window). Every conversation, the default one included, is also a sessions/ row of type dedicated-agent; read any of them with GET /sessions/{id}/fetch/, as the app does for its conversation list.
Auth: Session token · In the app: Dedicated Agent console (on open)
Query parameters
| Field | Type | Required | Description |
|---|---|---|---|
limit | integer | no | Default: 100. |
Response 200 — Messages.
| Field | Type | Description |
|---|---|---|
agent_id | string | |
messages | object[] | |
messages[].id | integer | |
messages[].role | string ("user", "assistant") | |
messages[].message | string | |
messages[].created_at | string (date-time) |
Example
bash
curl -X GET "https://api.example.com/microservices/dedicated-agent/messages/" \
-H "Authorization: Token $FINBLADE_TOKEN"GET /microservices/dedicated-agent/activity/
Activity log and spend
Every platform tool the agent called (newest first) and its LLM spend against the budget.
Auth: Session token · In the app: Dedicated Agent → Activity
Query parameters
| Field | Type | Required | Description |
|---|---|---|---|
limit | integer | no | Default: 50. |
Response 200 — Activity.
| Field | Type | Description |
|---|---|---|
agent_id | string | |
status | string ("running", "paused", "stopped", "provisioning") | |
activity | object[] | |
activity[].tool_name | string | |
activity[].success | boolean | |
activity[].duration_ms | integer | |
activity[].ts | string (date-time) | |
spend | object, nullable | |
spend.spend | number | |
spend.soft_budget | number, nullable |
json
{
"agent_id": "agt_42",
"status": "running",
"activity": [
{
"tool_name": "send_email",
"success": true,
"duration_ms": 812,
"ts": "2026-09-22T08:03:10Z"
}
],
"spend": {
"spend": 12.4,
"soft_budget": 50
}
}Response 404 — No dedicated agent.
Example
bash
curl -X GET "https://api.example.com/microservices/dedicated-agent/activity/" \
-H "Authorization: Token $FINBLADE_TOKEN"POST /microservices/dedicated-agent/kill/
Pause the agent
Soft pause — the console stops routing to the agent and the gateway is asked to stop. Resuming is done by an operator.
Auth: Session token · In the app: Dedicated Agent → Pause
Response 200 — Paused.
| Field | Type | Description |
|---|---|---|
success | boolean | |
status | string | |
note | string |
Response 404 — No dedicated agent.
Example
bash
curl -X POST "https://api.example.com/microservices/dedicated-agent/kill/" \
-H "Authorization: Token $FINBLADE_TOKEN"GET /microservices/dedicated-agent/jobs/
Scheduled jobs
Auth: Session token · In the app: Dedicated Agent → Jobs
Query parameters
| Field | Type | Required | Description |
|---|---|---|---|
include_disabled | boolean | no |
Response 200 — Jobs (gateway response).
| Field | Type | Description |
|---|---|---|
jobs | object[] | |
jobs[].id | string | |
jobs[].name | string | |
jobs[].prompt | string | What the agent does when the job fires. |
jobs[].schedule | object | Machine schedule (kind: interval, cron or once, …). |
jobs[].schedule_display | string | Human-readable, e.g. every day 9am. |
jobs[].enabled | boolean | |
jobs[].state | string ("scheduled", "paused", "completed", "error") | |
jobs[].next_run_at | string (date-time), nullable | |
jobs[].last_run_at | string (date-time), nullable | |
jobs[].last_status | string, nullable | |
jobs[].last_error | string, nullable | |
jobs[].repeat | object | |
jobs[].repeat.times | integer, nullable | null = forever. |
jobs[].repeat.completed | integer | |
jobs[].latest_execution | object, nullable | The most recent run (status, timestamps). |
Response 502 — Agent unreachable.
Example
bash
curl -X GET "https://api.example.com/microservices/dedicated-agent/jobs/" \
-H "Authorization: Token $FINBLADE_TOKEN"GET /microservices/dedicated-agent/jobs/{job_id}/
One job
Auth: Session token
Path parameters
| Field | Type | Required | Description |
|---|---|---|---|
job_id | string | yes |
Response 200 — The job.
| Field | Type | Description |
|---|---|---|
id | string | |
name | string | |
prompt | string | What the agent does when the job fires. |
schedule | object | Machine schedule (kind: interval, cron or once, …). |
schedule_display | string | Human-readable, e.g. every day 9am. |
enabled | boolean | |
state | string ("scheduled", "paused", "completed", "error") | |
next_run_at | string (date-time), nullable | |
last_run_at | string (date-time), nullable | |
last_status | string, nullable | |
last_error | string, nullable | |
repeat | object | |
repeat.times | integer, nullable | null = forever. |
repeat.completed | integer | |
latest_execution | object, nullable | The most recent run (status, timestamps). |
json
{
"id": "job_7a1",
"name": "Morning briefing",
"prompt": "Summarise overnight emails and today's calendar.",
"schedule": {
"kind": "cron",
"expr": "0 9 * * 1-5"
},
"schedule_display": "every weekday 9am",
"enabled": true,
"state": "scheduled",
"next_run_at": "2026-09-23T09:00:00+03:00",
"last_run_at": "2026-09-22T09:00:00+03:00",
"last_status": "completed",
"last_error": null,
"repeat": {
"times": null,
"completed": 14
},
"latest_execution": {
"status": "completed"
}
}Example
bash
curl -X GET "https://api.example.com/microservices/dedicated-agent/jobs/<job_id>/" \
-H "Authorization: Token $FINBLADE_TOKEN"DELETE /microservices/dedicated-agent/jobs/{job_id}/
Delete a job
Auth: Session token
Path parameters
| Field | Type | Required | Description |
|---|---|---|---|
job_id | string | yes |
Response 200 — Deleted.
Example
bash
curl -X DELETE "https://api.example.com/microservices/dedicated-agent/jobs/<job_id>/" \
-H "Authorization: Token $FINBLADE_TOKEN"POST /microservices/dedicated-agent/jobs/{job_id}/{action}/
Pause, resume or run a job now
Auth: Session token
Path parameters
| Field | Type | Required | Description |
|---|---|---|---|
job_id | string | yes | |
action | string ("pause", "resume", "run") | yes |
Response 200 — Done (gateway response).
Response 400 — Unknown action, or the gateway refused (e.g. resuming a one-shot whose time has passed — error explains).
Example
bash
curl -X POST "https://api.example.com/microservices/dedicated-agent/jobs/<job_id>/run/" \
-H "Authorization: Token $FINBLADE_TOKEN"POST /microservices/dedicated-agent/runs/
Start an autonomous run
Hands the agent a task to complete on its own. Follow it with GET …/runs/{run_id}/ or the event stream; approve tool use when it pauses in waiting_for_approval.
A run starts a fresh session, so it does not inherit a conversation's thinking level: send reasoning_effort to choose one (otherwise your saved default, else medium), and the run is placed on the model for that level — the same one a console turn at that level uses. Naming a model yourself overrides that choice.
Auth: Session token · In the app: Dedicated Agent → Autopilot
Request body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
input | string | yes | The task. |
instructions | string | no | Extra guidance. |
reasoning_effort | string ("minimal", "low", "medium", "high", "xhigh", "none") | no | Thinking level for the run. Read by Finblade, not passed to the agent. |
model | string | no | Explicit model; skips the thinking-level choice. |
json
{
"input": "Audit last month's invoices for duplicates and prepare a report.",
"reasoning_effort": "high"
}Response 202 — Accepted; the run proceeds in the background. The agent's own response is passed through — the id is run_id or id.
| Field | Type | Description |
|---|---|---|
id | string | Also returned as run_id. |
status | string ("started", "queued", "running", "waiting_for_approval", "stopping", "completed", "failed", "cancelled") | |
input | string | |
instructions | string | |
model | string | |
output | string, nullable | Final answer when completed. |
created_at | string (date-time) | |
updated_at | string (date-time) |
json
{
"id": "run_3f2e",
"status": "running",
"input": "Audit last month's invoices for duplicates and prepare a report.",
"model": "default",
"output": null,
"created_at": "2026-09-22T08:00:00Z",
"updated_at": "2026-09-22T08:03:10Z"
}Response 409 — The agent is not running.
Response 503 — Agent unreachable (it may be restarting).
Example
bash
curl -X POST "https://api.example.com/microservices/dedicated-agent/runs/" \
-H "Authorization: Token $FINBLADE_TOKEN" \
-H "Content-Type: application/json" \
-d '{"input":"Audit last month's invoices for duplicates and prepare a report.","reasoning_effort":"high"}'GET /microservices/dedicated-agent/runs/{run_id}/
Run status
Auth: Session token
Path parameters
| Field | Type | Required | Description |
|---|---|---|---|
run_id | string | yes |
Response 200 — The run.
| Field | Type | Description |
|---|---|---|
id | string | Also returned as run_id. |
status | string ("started", "queued", "running", "waiting_for_approval", "stopping", "completed", "failed", "cancelled") | |
input | string | |
instructions | string | |
model | string | |
output | string, nullable | Final answer when completed. |
created_at | string (date-time) | |
updated_at | string (date-time) |
json
{
"id": "run_3f2e",
"status": "running",
"input": "Audit last month's invoices for duplicates and prepare a report.",
"model": "default",
"output": null,
"created_at": "2026-09-22T08:00:00Z",
"updated_at": "2026-09-22T08:03:10Z"
}Response 404 — Unknown run.
Example
bash
curl -X GET "https://api.example.com/microservices/dedicated-agent/runs/<run_id>/" \
-H "Authorization: Token $FINBLADE_TOKEN"GET /microservices/dedicated-agent/runs/{run_id}/events/
Run event stream
Server-Sent Events from the gateway for one run (tool calls, approvals, output). Open with EventSource or any SSE client.
Auth: Session token
Path parameters
| Field | Type | Required | Description |
|---|---|---|---|
run_id | string | yes |
Response 200 — SSE stream.
Content type: text/event-stream
Example
bash
curl -X GET "https://api.example.com/microservices/dedicated-agent/runs/<run_id>/events/" \
-H "Authorization: Token $FINBLADE_TOKEN"POST /microservices/dedicated-agent/runs/{run_id}/{action}/
Approve a tool call, or stop the run
approval answers a pending approval with choice (once, session, always or deny; add all: true to apply to every pending request). stop cancels the run.
Auth: Session token
Path parameters
| Field | Type | Required | Description |
|---|---|---|---|
run_id | string | yes | |
action | string ("approval", "stop") | yes |
Request body (application/json, optional)
| Field | Type | Required | Description |
|---|---|---|---|
choice | string ("once", "session", "always", "deny") | no | |
all | boolean | no |
json
{
"choice": "once"
}Response 200 — Done (gateway response).
Response 400 — Unknown action.
Example
bash
curl -X POST "https://api.example.com/microservices/dedicated-agent/runs/<run_id>/<action>/" \
-H "Authorization: Token $FINBLADE_TOKEN" \
-H "Content-Type: application/json" \
-d '{"choice":"once"}'