API reference¶
A quick reference to the HTTP endpoints you are most likely to call directly — for scripting, automation, or debugging. TheYgent has two services, each with its own base URL:
- Control plane —
http://localhost:8080— agents, runs, sessions, triggers, connections, artifacts, observability. - Inference plane —
http://localhost:8081— the OpenAI-compatible data plane (/v1/*) and model management (/admin/*).
The interface uses these same endpoints, so anything you can do in the UI you can do here. This page lists the user-facing surface; it is not the full internal API.
Wire conventions
Control-plane request bodies and stored run/session records use snake_case (session_id, content_hash). The immediate run result envelope and streaming (SSE) frames use camelCase (runId). The inference plane (/v1/* and /admin/*) is camelCase throughout. The graph document (ir) is always camelCase. Keep them straight when you assemble a body.
Authentication
On a local install the control plane's interactive endpoints are open — there is no per-request auth in front of runs, agents, or sessions. Two surfaces are the exception and carry real auth: POST /agents/{id}/invoke (a bearer token, THEYGENT_INVOKE_TOKEN) and webhook delivery POST /hooks/{id} (an HMAC signature). Do not expose the control plane to an untrusted network.
Control plane¶
Health¶
| Method | Path | Purpose |
|---|---|---|
| GET | /healthz |
Liveness — is the process up? Returns {"status":"ok"}. |
| GET | /readyz |
Readiness — 200 when ready, 503 not-ready naming the down dependency (database or inference plane). |
Agents¶
Saved agents are immutable, content-addressed versions. See Saving agents and Agent versioning.
| Method | Path | Purpose |
|---|---|---|
| POST | /agents |
Publish a new agent from an IR document. Body {ir, name?}. 201; reusing an existing id → 409 agent_exists. |
| GET | /agents |
List agents, newest first (limit 1–200 default 50, before cursor). |
| GET | /agents/{id} |
One agent with its versions, newest first. |
| POST | /agents/{id}/versions |
Publish a new version. Identical content under an existing version is an idempotent 200; different content under the same version → 409 version_conflict. |
| GET | /agents/{id}/versions/{version} |
The full stored IR + canvas layout for one version. |
| GET / PUT | /agents/{id}/io-policy |
Read/set the per-agent I/O capture policy. PUT body {io_capture, io_retention_seconds?, redact_rules?}. Setting it never changes the content hash. |
There is no endpoint to delete an agent or a version — published versions are permanent.
Runs¶
Statuses: created → streaming → waiting → completed | failed. See Runs & sessions.
| Method | Path | Purpose |
|---|---|---|
| POST | /runs |
Plain prompt run. Body {input, model, params?, stream?, session_id?}. model is a logical id. Streams SSE by default. |
| POST | /graphs/runs |
Run an inline IR graph. Body {ir, input, stream?, session_id?}. Invalid IR → 400 invalid_ir (no run row created). |
| POST | /agents/{id}/runs |
Run a saved agent by reference. Body {input, version?, content_hash?, session_id?, stream?}. |
| POST | /agents/{id}/invoke |
Token-authed, non-interactive sibling of the above. Same body but stream defaults false. Requires a bearer token. |
| POST | /agents/{id}/durable-runs |
Run a saved agent on the durable runtime (the only way to run human/subgraph/loop/map agents). Returns 202 {run_id}; poll GET /runs/{id}. Needs durable mode. |
| GET | /runs |
List runs, newest first (limit, before). |
| GET | /runs/{id} |
Run detail, including output, error, content_hash, trigger_id, awaiting_node, completed_at. |
| POST | /runs/{id}/resume |
Deliver input to a run paused (waiting) at a human node. Body {input}. Returns 202. |
Start a streaming prompt run:
curl -N -X POST http://localhost:8080/runs \
-H 'Content-Type: application/json' \
-d '{"input": "Summarize the theory of relativity.", "model": "triage-fast", "stream": true}'
The stream is Server-Sent Events: run (status frames), delta (answer tokens), reasoning (model thinking, kept out of the output), terminated by data: [DONE]. Set "stream": false for a single JSON response {runId, status, output}.
Run a saved agent (non-streaming) with a session:
curl -X POST http://localhost:8080/agents/agent.support/runs \
-H 'Content-Type: application/json' \
-d '{"input": {"question": "Where is my order?"}, "session_id": "ses_abc", "stream": false}'
Invoke an agent with the invoke token:
curl -X POST http://localhost:8080/agents/agent.support/invoke \
-H 'Authorization: Bearer YOUR_INVOKE_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"input": {"question": "Where is my order?"}}'
Resume a waiting run:
curl -X POST http://localhost:8080/runs/RUN_ID/resume \
-H 'Content-Type: application/json' \
-d '{"input": {"approved": true}}'
Observability¶
Per-run trace data. See Observability.
| Method | Path | Purpose |
|---|---|---|
| GET | /runs/{id}/trace |
The persisted span tree (timing, status, attribution) — no payloads. |
| GET | /runs/{id}/trace/stream |
Live SSE overlay: events span.open, span.close, done; : keepalive comment every 15s. |
| GET | /runs/{id}/nodes/{node_id}/io |
Lazy per-node input/output payloads, gated by the capture policy (a gated state is a reason, never an error). |
Triggers & webhooks¶
A trigger deploys a saved, pinned agent behind an unattended entry point. See Triggers & webhooks.
| Method | Path | Purpose |
|---|---|---|
| POST | /triggers |
Create a trigger. Body {agent_id, kind, version?|content_hash?, config, enabled?}. Pin exactly one of version/content_hash. |
| GET | /triggers |
List triggers (webhook secrets redacted to "***"). |
| GET / PATCH / DELETE | /triggers/{id} |
Read / update (enabled, config only — kind and pin are immutable) / delete a trigger. |
| POST | /hooks/{id} |
Fire a webhook trigger. The raw JSON body is the run input; requires the X-Theygent-Signature header. Returns 202. |
Trigger config keys: schedule needs config.cron (a valid cron expression) and takes optional config.input; webhook needs config.secret (the inbound signing secret).
Fire a webhook — the signature is the HMAC-SHA256 of the raw request body keyed by the trigger's secret:
BODY='{"question":"Where is my order?"}'
SIG=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "YOUR_WEBHOOK_SECRET" | awk '{print $2}')
curl -X POST http://localhost:8080/hooks/TRIGGER_ID \
-H "X-Theygent-Signature: sha256=$SIG" \
-H 'Content-Type: application/json' \
-d "$BODY"
A bad or missing signature → 401 invalid_signature; a disabled trigger → 409 trigger_disabled.
Sessions¶
Opt-in conversational memory. See Runs & sessions.
| Method | Path | Purpose |
|---|---|---|
| GET | /sessions |
List sessions, newest activity first. |
| GET | /sessions/{id} |
Session detail with messages in order. |
| POST | /sessions |
Create/ensure a session. Body {id?, metadata?}; a missing id is minted server-side. |
| POST | /sessions/{id}/turns |
Append a {user_content, assistant_content} pair (both non-blank). |
| DELETE | /sessions/{id} |
Delete the session and its messages; its runs are detached, not deleted. |
Connections¶
Named tool/MCP credentials. The secret is write-only and never returned. See Tools.
| Method | Path | Purpose |
|---|---|---|
| POST | /connections |
Create. Body {name, kind, config, secret?, enabled?}. kind is http_auth or mcp_server. |
| GET | /connections |
List (responses expose hasSecret only; secret-ish config keys redacted). |
| GET / PATCH / DELETE | /connections/{id} |
Read / update (a non-empty secret rotates in place without changing any content hash) / delete. |
Artifacts¶
Audio/image blobs by reference. See Voice.
| Method | Path | Purpose |
|---|---|---|
| POST | /artifacts |
Upload raw bytes (the Content-Type header is the stored mime). Returns 201 {ref, contentType, bytes}. |
| GET | /artifacts/{ref} |
Fetch a stored art_… blob (only art_* ids are served). |
curl -X POST http://localhost:8080/artifacts \
-H 'Content-Type: audio/webm' \
--data-binary @recording.webm
MCP servers¶
Register external tool servers. See MCP tools.
| Method | Path | Purpose |
|---|---|---|
| PUT / GET / DELETE | /admin/mcp/servers/{name} |
Register / read / remove a server config. |
| GET | /admin/mcp/servers |
List registered servers (env values are never echoed). |
| GET | /admin/mcp/servers/{name}/tools |
List the server's tools (lazy-connects; unreachable → 503 mcp_unavailable). |
| POST | /admin/mcp/servers/{name}:warm / :close |
Start / stop the server process. |
Bench store¶
The Bench records results and presets here; testing itself runs against the inference plane. See The Bench.
| Method | Path | Purpose |
|---|---|---|
| POST / GET | /bench/runs |
Record / list bench results (filter by logical_id, agent_id, suite_id, case_id). |
| GET | /bench/compare?a=&b= |
Per-metric deltas between two saved results. |
| POST / GET / DELETE | /bench/presets |
Save / list / delete named param presets. |
| POST / GET | /bench/suites |
Store / list golden-case suites (API-only; no UI yet). |
Inference plane¶
The data plane is OpenAI-compatible. In every /v1/* call, the model field is a logical id you registered — never an engine name. See Models & engines.
Data plane (/v1/*)¶
| Method | Path | Purpose |
|---|---|---|
| GET | /v1/models |
List registered logical ids as OpenAI model objects. |
| POST | /v1/chat/completions |
Chat (and vision — messages content may be text + image_url parts). Streaming and non-streaming. |
| POST | /v1/embeddings |
Embeddings. input is a string or list of strings. |
| POST | /v1/audio/transcriptions |
Speech-to-text. Multipart form with model + file. |
| POST | /v1/audio/speech |
Text-to-speech. {model, input, voice?}; returns raw audio bytes. |
| POST | /v1/images/generations |
Text-to-image. {model, prompt, size?, n?, steps?}; returns {data:[{b64_json}]}. |
curl http://localhost:8081/v1/chat/completions \
-H 'Content-Type: application/json' \
-d '{"model": "triage-fast", "messages": [{"role":"user","content":"Hello"}]}'
Model management (/admin/*)¶
| Method | Path | Purpose |
|---|---|---|
| PUT | /admin/models/{id} |
Register/replace a model under a logical id. |
| GET | /admin/models |
List registered models with live state. |
| GET / DELETE | /admin/models/{id} |
Read one / unregister (evicts then deletes). |
| GET | /admin/models/{id}/capabilities |
Probe tool-calling, vision, reasoning, max context, modalities. |
| POST | /admin/models/{id}:warm / :evict |
Pre-load / free the engine. |
| GET | /admin/engines |
Currently resident engines and maxResident. |
| GET | /admin/credentials |
List local credential names with hasValue (values are never read back). |
| PUT / DELETE | /admin/credentials/{name} |
Set / remove a local credential (values are write-only). |
| GET | /admin/catalog/models |
Browse installable models (search, sort, limit, engines, size, modality). |
| GET | /admin/catalog/models/{repo} |
Model detail with per-quant variants and RAM fit badges. |
| POST | /admin/catalog/install |
Start a download+install job. Body {repo, engine, variantId, logicalId}. |
| GET | /admin/catalog/downloads / /{job_id} |
Track download progress. |
| POST | /admin/catalog/downloads/{job_id}:cancel |
Cancel an in-flight install. |
Register a hosted, OpenAI-compatible model:
curl -X PUT http://localhost:8081/admin/models/claude-fast \
-H 'Content-Type: application/json' \
-d '{"binding":"openai-compatible","baseUrl":"https://api.example.com/v1","model":"provider-model-name","credentialRef":"secret://MY_API_KEY"}'
See Remote models for the reachable-binding fields.
Health¶
| Method | Path | Purpose |
|---|---|---|
| GET | /healthz |
Liveness. |
| GET | /readyz |
Per-(engine, modality) readiness — each slot with a reason and install hint when not ready. Stays 200 while any engine is available. |
Related pages¶
- Environment variables — the
THEYGENT_*knobs these services read. - Troubleshooting — what the error codes mean and how to fix them.
- Glossary — terms used above (logical id, binding, run, trigger, artifact).