Everything you need: MCP tools, REST endpoints, data model, and behavioral guide. Single-page reference — use the sidebar to jump to any section.
Three paths to connect an agent. Pick the one that fits. All three give you the same execution state layer.
Hosted MCP server — one command connects. No git clone, no npm install, no build step.
Then install the skill: curl -sL .../SKILL.md -o ~/.claude/skills/threadron/SKILL.md --create-dirs. Restart Claude Code. MCP tools reference ↓
Hosted MCP server — one command connects. Then add the skill to your system prompt.
Add skill instructions to your system prompt. Full guide →
No MCP required. Copy skill.md into your agent's system prompt. Direct HTTP calls.
All auth via Authorization: Bearer $TFA_API_KEY. REST reference ↓
Self-hosted? Run docker compose up -d, then curl http://localhost:8080/v1/auth/setup to generate your first key. Use http://localhost:8080/v1 as your TFA_API_URL.
11 tools exposed by the Threadron MCP server. These are the native interface for Claude Code and OpenClaw. Each tool maps to one or more REST endpoints — you never make raw HTTP calls from an MCP agent.
No parameters. Call this at the start of every session before doing anything else.
If in_progress is non-empty, call threadron_get_task on those items first to reconstruct state before picking up new work.
| Parameter | Required | Description |
|---|---|---|
| status | optional | Filter by status: pending, in_progress, blocked, completed |
| assignee | optional | Filter by agent ID string |
| domain_id | optional | Filter by domain ID (e.g. d_abc123) |
| search | optional | Case-insensitive substring match against task title |
| Parameter | Required | Description |
|---|---|---|
| task_id | required | Work item ID (e.g. t_abc123) |
| Parameter | Required | Description |
|---|---|---|
| title | required | Short label for the work item |
| domain_id | required | Domain this item belongs to (get from threadron_list_domains) |
| goal | optional* | What this work aims to achieve — include this |
| outcome_definition | optional* | Measurable definition of done — include this |
| current_state | optional | What's known right now about the current state |
| next_action | optional | What should happen next |
| assignee | optional | Agent ID to assign (defaults to the calling agent) |
| priority | optional | low, medium, high, urgent — defaults to medium |
| project_id | optional | Project grouping (get from REST GET /v1/projects) |
* Technically optional but strongly recommended — these fields make handoff possible.
| Parameter | Required | Description |
|---|---|---|
| task_id | required | Work item ID |
| status | optional | pending, in_progress, blocked, completed |
| current_state | optional | Machine-readable summary of where things stand right now |
| next_action | optional | What should happen next (write for the next reader) |
| blockers | optional | Array of strings — set to [] to clear all blockers |
| confidence | optional | low, medium, high |
| Parameter | Required | Description |
|---|---|---|
| task_id | required | Work item ID |
| type | required | Entry type (see enum below) |
| body | required | Content — what happened, what was decided, what was observed |
| Type | When to use | |
|---|---|---|
| observation | Something discovered — test results, code behavior, unexpected output | |
| action_taken | An action performed — file edited, command run, API called, branch pushed | |
| decision | A choice made — include the reasoning; especially useful for architectural decisions | |
| blocker | Something preventing progress — include what is needed to unblock | |
| proposal | A proposed approach pending review or approval | |
| handoff | Summary for the next agent/session — pair with update_state on session end | |
| state_transition | Status or guardrail change (also auto-generated by system on PATCH) | |
| Parameter | Required | Description |
|---|---|---|
| task_id | required | Work item ID to attach to |
| type | required | Artifact type (see enum below) |
| title | required | Short human-readable label |
| uri | optional | URL or file path (use for branch, commit, PR, file) |
| body | optional | Inline content — use for patch text, plan markdown, terminal output |
| Parameter | Required | Description |
|---|---|---|
| task_id | required | Work item ID to claim |
| duration_minutes | optional | How long to hold the claim (default: 60). Re-claim if work takes longer. |
If you receive a 409 and claim_expires_at is in the past, the claim is stale — you can claim it. Always claim before calling threadron_update_state.
| Parameter | Required | Description |
|---|---|---|
| task_id | required | Work item ID to release |
Clears claimed_by and claim_expires_at. Auto-generates a release context entry. Always update state before releasing so the next session has context.
No parameters.
No parameters.
Full HTTP API. Base URL: https://threadron.com/v1 (managed) or http://localhost:8080/v1 (self-hosted). All authenticated endpoints require Authorization: Bearer $TFA_API_KEY.
| Method | Path | Description |
|---|---|---|
| GET | /v1/health | No auth. Returns {"status":"ok"} |
| Method | Path | Description |
|---|---|---|
| POST | /v1/auth/setup | First-run only. No auth. Creates initial API key. Returns 409 if any key exists. |
| POST | /v1/auth/keys | Create additional API key. Body: {"name":"ci-bot","agent_id":"..."}. Key shown once. |
| GET | /v1/auth/keys | List all API keys (values redacted). |
| DELETE | /v1/auth/keys/:id | Revoke a key. Returns {"success":true} |
| Method | Path | Description |
|---|---|---|
| POST | /v1/domains | Create domain. Body: {"name":"backend","default_guardrail":"autonomous"} |
| GET | /v1/domains | List all domains. Returns {"domains":[...]} |
| PATCH | /v1/domains/:id | Update name or default_guardrail. |
| DELETE | /v1/domains/:id | Cascades to projects and tasks. Returns {"deleted":true} |
default_guardrail values: autonomous, notify, approval_required. Defaults to autonomous.
| Method | Path | Description |
|---|---|---|
| POST | /v1/projects | Create project. Body: {"name":"API v2","domain_id":"d_...","description":"..."} |
| GET | /v1/projects | List projects. Optional filter: ?domain_id=d_abc123. Returns {"projects":[...]} |
| GET | /v1/projects/:id | Get single project or 404. |
| PATCH | /v1/projects/:id | Update name or description. |
| DELETE | /v1/projects/:id | Returns {"deleted":true} |
| Method | Path | Description |
|---|---|---|
| POST | /v1/tasks | Create work item. Full body below. |
| GET | /v1/tasks | List with filters: ?assignee=&status=&domain_id=&project_id=&guardrail=&search= |
| GET | /v1/tasks/:id | Full task with embedded context and artifacts arrays. |
| PATCH | /v1/tasks/:id | Update any field. Include _actor and _actor_type for event attribution. |
| DELETE | /v1/tasks/:id | Deletes task, context, and artifacts. Returns {"deleted":true} |
| Method | Path | Description |
|---|---|---|
| POST | /v1/tasks/:id/context | Append an entry. Append-only — no edit or delete. |
| GET | /v1/tasks/:id/context | All entries in chronological order. Returns {"context":[...]} |
Types in gray are auto-generated by the system. You don't need to write them manually.
| Method | Path | Description |
|---|---|---|
| POST | /v1/tasks/:id/artifacts | Create artifact attached to a task. Auto-generates artifact_created context entry. |
| GET | /v1/tasks/:id/artifacts | All artifacts for a task in chronological order. Returns {"artifacts":[...]} |
| GET | /v1/artifacts/:id | Single artifact by ID. |
| Method | Path | Description |
|---|---|---|
| POST | /v1/tasks/:id/claim | Claim a work item. 409 if already claimed (non-expired). Auto-generates claim context entry. |
| POST | /v1/tasks/:id/release | Release a claim. Auto-generates release context entry. |
| Method | Path | Description |
|---|---|---|
| POST | /v1/agents | Register an agent. Agent supplies its own ID. |
| GET | /v1/agents | List all agents. last_seen updated on every authenticated request. Returns {"agents":[...]} |
| GET | /v1/agents/:id | Single agent or 404. |
| PATCH | /v1/agents/:id | Update name, type, or capabilities. |
Key-value store for preferences and operational settings. Values are arbitrary JSON.
| Method | Path | Description |
|---|---|---|
| POST | /v1/config | Create or update (upsert). Body: {"key":"onboarding_complete","value":true} |
| GET | /v1/config | All config entries. Returns {"config":[...]} |
| GET | /v1/config/:key | Single entry by key or 404. |
| PATCH | /v1/config/:key | Update existing entry. |
| Key | Type | Description |
|---|---|---|
| onboarding_complete | boolean | Whether the setup flow has been completed |
| approval_behavior | string | ask_immediately, collect_and_summarize, or end_of_session |
| default_agent_id | string | Primary agent ID for this installation |
| timezone | string | e.g. America/New_York |
The five core objects. ID prefixes: tasks t_, domains d_, projects p_, context entries ctx_, artifacts art_, API keys key_. Agent IDs are free-form strings.
The atomic unit of work. Carries structured execution state — not just a title and a checkbox.
Append-only event log entry. The persistent memory of the work item — every state change, decision, and observation lives here.
First-class output objects. Not buried in notes — queryable, linkable, part of the structured record.
How to be a good Threadron citizen. These are the behavioral rules baked into the skill — the "why" behind every tool call pattern.
The critical rule: Every time you change what you're doing, call BOTH threadron_update_state (the structured WHAT) AND threadron_add_context (the narrative WHY). A state update without a context entry leaves the timeline empty and makes the work item useless for handoff.
Call threadron_checkin at the start of every session. It returns in-progress, pending, and blocked work in one call. This is your orientation.
If in_progress is non-empty, call threadron_get_task on each item. Read current_state, next_action, blockers, and the full context timeline. This is how you pick up where you left off without re-investigating.
Always call threadron_claim before working on an item. This sets a time-bounded lock so two agents can't collide. If you get a 409, the item is taken — move on or wait.
Use this pattern at every meaningful step while working. Always log context first, then update state.
| Situation | Context type | State update |
|---|---|---|
| Discovered something | observation | Update current_state |
| Made a choice | decision | Update next_action |
| Completed a step | action_taken | Update both current_state and next_action |
| Hit a wall | blocker | Add to blockers[], set status: "blocked" |
| Produced output | action_taken | Also call threadron_create_artifact |
Before the session ends or when switching to other work, leave a clean handoff:
Call threadron_add_context(type: "action_taken", body: "Pausing. [Summary of what was done...]")
Call threadron_update_state with an accurate current_state and a precise next_action. Write for the reader who has never seen this item before.
Call threadron_release. This makes the item available for other agents. If the work is complete, set status: "completed" first.
When multiple agents share a work queue, follow these rules to avoid collisions:
Claim collision (409): The item is taken. Check claim_expires_at — if it's in the past, the claim is stale and you can claim it. Otherwise move on.
Checking assignee: If assignee is set to a different agent and their claim is active, leave the item alone even if you could technically claim it.
Before releasing a partial item: Always set current_state and next_action so the next agent knows exactly where to start. This is the entire point of the system.
Check the task's guardrail field (falls back to domain default_guardrail) before acting:
| Level | Behavior | |
|---|---|---|
| autonomous | Proceed without asking. Act freely. | |
| notify | Act, then notify the user. Add an action_taken context entry describing what was done. | |
| approval_required | Stop. Add an approval_requested context entry. Set status: "blocked". Wait for human input. When approval comes, add approval_received, clear blockers, resume. | |
Write state for the next reader, not yourself. A different session — possibly a different agent — should pick up any item and immediately understand what's going on without re-investigating.
The timeline IS the story. If the context log is empty, the work item is useless for handoff. Every state change needs a context entry explaining it.
Search before creating. Call threadron_list_tasks with a search query before creating a new item. Avoid duplicates in the shared queue.
All outputs are artifacts. Every file, branch, commit, PR, patch, or plan produced should be recorded. Not in a note — as a first-class artifact object.
On first connection, check GET /v1/config/onboarding_complete. If missing or false, run the setup flow: