Reference

Docs.

Everything you need: MCP tools, REST endpoints, data model, and behavioral guide. Single-page reference — use the sidebar to jump to any section.

Quick Start MCP Tools REST API Data Model Behavioral Guide
01

Quick Start

Three paths to connect an agent. Pick the one that fits. All three give you the same execution state layer.

Recommended — no install

Claude Code

Hosted MCP server — one command connects. No git clone, no npm install, no build step.

bash claude mcp add --transport http threadron https://threadron.com/mcp --header "Authorization: Bearer YOUR_API_KEY"

Then install the skill: curl -sL .../SKILL.md -o ~/.claude/skills/threadron/SKILL.md --create-dirs. Restart Claude Code. MCP tools reference ↓

No install

OpenClaw

Hosted MCP server — one command connects. Then add the skill to your system prompt.

bash openclaw mcp set threadron '{"url":"https://threadron.com/mcp","headers":{"Authorization":"Bearer YOUR_API_KEY"}}'

Add skill instructions to your system prompt. Full guide →

Any Agent

REST / HTTP

No MCP required. Copy skill.md into your agent's system prompt. Direct HTTP calls.

env TFA_API_URL=https://threadron.com/v1 TFA_API_KEY=tfa_sk_... TFA_AGENT_ID=your-agent

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.

02

MCP Tools Reference

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.

threadron_checkin Session start check-in. Composite call — returns in-progress, pending, and blocked work in one shot.

No parameters. Call this at the start of every session before doing anything else.

Response { "in_progress": [...], // Tasks assigned to you, status=in_progress "pending": [...], // Tasks assigned to you, status=pending "blocked": [...], // All blocked tasks across the workspace "summary": "2 in progress, 3 pending, 1 blocked" }

If in_progress is non-empty, call threadron_get_task on those items first to reconstruct state before picking up new work.

threadron_list_tasks List and filter work items. Use when you need more control than checkin provides.
ParameterRequiredDescription
statusoptionalFilter by status: pending, in_progress, blocked, completed
assigneeoptionalFilter by agent ID string
domain_idoptionalFilter by domain ID (e.g. d_abc123)
searchoptionalCase-insensitive substring match against task title
Response [...task objects] // Array of work items matching filters
threadron_get_task Full work item detail — goal, state, timeline, artifacts. Use before starting work.
ParameterRequiredDescription
task_idrequiredWork item ID (e.g. t_abc123)
Response — full task object { "id": "t_abc123", "title": "...", "status": "in_progress", "goal": "...", "current_state": "...", "next_action": "...", "blockers": [], "confidence": "high", "context": [...], // Full event timeline in chronological order "artifacts": [...] // All attached artifacts }
threadron_create_task Create a new work item with structured state. Always set goal and outcome_definition.
ParameterRequiredDescription
titlerequiredShort label for the work item
domain_idrequiredDomain this item belongs to (get from threadron_list_domains)
goaloptional*What this work aims to achieve — include this
outcome_definitionoptional*Measurable definition of done — include this
current_stateoptionalWhat's known right now about the current state
next_actionoptionalWhat should happen next
assigneeoptionalAgent ID to assign (defaults to the calling agent)
priorityoptionallow, medium, high, urgent — defaults to medium
project_idoptionalProject grouping (get from REST GET /v1/projects)

* Technically optional but strongly recommended — these fields make handoff possible.

Response { "id": "t_newid", "title": "...", "status": "pending", // ... all task fields }
threadron_update_state Update execution state. Call frequently — this is the structured record that lets the next session pick up where you left off.
ParameterRequiredDescription
task_idrequiredWork item ID
statusoptionalpending, in_progress, blocked, completed
current_stateoptionalMachine-readable summary of where things stand right now
next_actionoptionalWhat should happen next (write for the next reader)
blockersoptionalArray of strings — set to [] to clear all blockers
confidenceoptionallow, medium, high
Response // Updated task object. Status changes auto-generate a state_transition context entry.
threadron_add_context Add a timeline entry. The audit trail — use for observations, decisions, actions, blockers. State says WHAT; context says WHY.
ParameterRequiredDescription
task_idrequiredWork item ID
typerequiredEntry type (see enum below)
bodyrequiredContent — what happened, what was decided, what was observed
Type enum
TypeWhen to use
observationSomething discovered — test results, code behavior, unexpected output
action_takenAn action performed — file edited, command run, API called, branch pushed
decisionA choice made — include the reasoning; especially useful for architectural decisions
blockerSomething preventing progress — include what is needed to unblock
proposalA proposed approach pending review or approval
handoffSummary for the next agent/session — pair with update_state on session end
state_transitionStatus or guardrail change (also auto-generated by system on PATCH)
Response { "id": "ctx_abc123", "task_id": "t_abc123", "type": "decision", "body": "...", "author": "claude-code", "actor_type": "agent", "created_at": "2024-01-01T00:00:00.000Z" }
threadron_create_artifact Attach an artifact — branch, PR, commit, file, plan, doc, or terminal output. Record every meaningful output.
ParameterRequiredDescription
task_idrequiredWork item ID to attach to
typerequiredArtifact type (see enum below)
titlerequiredShort human-readable label
urioptionalURL or file path (use for branch, commit, PR, file)
bodyoptionalInline content — use for patch text, plan markdown, terminal output
Type enum
file branch commit pull_request patch plan doc terminal_output
Response { "id": "art_abc123", "task_id": "t_abc123", "type": "pull_request", "title": "Fix: connection pool race condition", "uri": "https://github.com/org/repo/pull/147", "body": null, "created_by": "claude-code", "created_at": "2024-01-01T00:00:00.000Z" } // Auto-generates an artifact_created context entry on the task.
threadron_claim Claim a work item before starting. Prevents other agents from working on the same item. Claims auto-expire.
ParameterRequiredDescription
task_idrequiredWork item ID to claim
duration_minutesoptionalHow long to hold the claim (default: 60). Re-claim if work takes longer.
Success — 200 // Updated task object with claimed_by and claim_expires_at set. Conflict — 409 (item already claimed) { "error": "Already claimed", "claimed_by": "other-agent", "claim_expires_at": "2024-01-01T01:00:00.000Z" }

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.

threadron_release Release your claim on a work item. Call this at session end or when switching to other work.
ParameterRequiredDescription
task_idrequiredWork 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.

threadron_list_domains List all available domains. Use to find domain IDs when creating work items.

No parameters.

Response [ { "id": "d_abc123", "name": "backend", "default_guardrail": "autonomous", "created_at": "..." } ]
threadron_list_agents List registered agents and their last activity timestamp.

No parameters.

Response [ { "id": "claude-code", "name": "Claude Code", "type": "coding-agent", "capabilities": ["code-generation", "debugging"], "last_seen": "2024-01-01T12:00:00.000Z" } ]
03

REST API Reference

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.

Auth header Authorization: Bearer tfa_sk_... // Error format — all errors return: {"error": "message describing the problem"} // Status codes: 200 success · 201 created · 400 bad request · 401 unauth · 404 not found · 409 conflict

Health

MethodPathDescription
GET /v1/health No auth. Returns {"status":"ok"}

Auth

MethodPathDescription
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}
POST /auth/setup — Response 201 { "id": "key_abc123", "api_key": "tfa_sk_k_abc123...", // Save immediately — shown once "name": "my-key" }

Domains

MethodPathDescription
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.

Projects

MethodPathDescription
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}

Tasks (Work Items)

MethodPathDescription
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}
POST /v1/tasks — full request body { "title": "Fix connection pool race condition", // required "domain_id": "d_abc123", // required "created_by": "claude-code", // required "project_id": "p_xyz789", // optional "assignee": "claude-code", // optional "priority": "high", // low | medium | high | urgent "guardrail": "approval_required", // overrides domain default "dependencies": ["t_dep001"], // optional "due_date": "2024-03-01T00:00:00.000Z", // ISO 8601 "tags": ["bug", "backend"], "metadata": {"github_issue": 42}, // arbitrary JSON "goal": "Eliminate intermittent timeouts under load.", "outcome_definition": "Zero errors at 500 rps in load test.", "current_state": "Not started.", "next_action": "Reproduce locally, identify locking gap.", "blockers": [], "confidence": "medium" }
PATCH /v1/tasks/:id — include actor attribution { "current_state": "Found root cause at pool.ts:47. Fix in progress.", "next_action": "Open PR after tests pass.", "_actor": "claude-code", "_actor_type": "agent" // agent | human | system } // Status + guardrail changes auto-generate state_transition context entries. // Assignee + claimed_by changes auto-generate handoff context entries.

Context (Event Timeline)

MethodPathDescription
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":[...]}
POST /v1/tasks/:id/context { "type": "decision", // required — see type enum "body": "Chose mutex over channel. Simpler.", // required "author": "claude-code", // required "actor_type": "agent" // agent | human | system }
Full type enum
observation action_taken decision blocker state_transition handoff proposal approval_requested approval_received artifact_created claim release

Types in gray are auto-generated by the system. You don't need to write them manually.

Artifacts

MethodPathDescription
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.
POST /v1/tasks/:id/artifacts { "type": "pull_request", // required "created_by": "claude-code", // required "title": "Fix: connection pool race condition", // optional "uri": "https://github.com/org/repo/pull/147", // URL or path "body": null, // inline content "metadata": {"pr_number": 147} // arbitrary JSON }
Type enum
file branch commit pull_request patch plan doc terminal_output

Claims

MethodPathDescription
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.
POST /v1/tasks/:id/claim { "agent_id": "claude-code", // required "duration_minutes": 60 // optional, default 30 } POST /v1/tasks/:id/release { "agent_id": "claude-code" // required }

Agents

MethodPathDescription
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.
POST /v1/agents { "id": "claude-code", // required — unique, stable "name": "Claude Code", // required — display name "type": "coding-agent", // optional, default "generic" "capabilities": ["code-generation", "debugging"] // optional JSON array }

Config

Key-value store for preferences and operational settings. Values are arbitrary JSON.

MethodPathDescription
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.
Standard Keys
KeyTypeDescription
onboarding_completebooleanWhether the setup flow has been completed
approval_behaviorstringask_immediately, collect_and_summarize, or end_of_session
default_agent_idstringPrimary agent ID for this installation
timezonestringe.g. America/New_York
04

Data Model

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.

Work Item (Task)

The atomic unit of work. Carries structured execution state — not just a title and a checkbox.

id
string — t_ prefix
Unique identifier
title
string
Short human-readable label
status
enum
pending · in_progress · blocked · completed
priority
enum
low · medium · high · urgent
goal
string | null
What this work aims to achieve — the "why"
outcome_definition
string | null
Measurable definition of done — what "complete" looks like
current_state
string | null
Machine-readable summary of where things stand right now
next_action
string | null
What should happen next — write for the next reader
blockers
string[]
Active blockers preventing progress
confidence
enum | null
low · medium · high — agent's confidence in completion
assignee
string | null
Agent or user ID assigned to this item
claimed_by
string | null
Agent currently holding the execution lock
claim_expires_at
ISO 8601 | null
When the claim auto-expires; past = claimable
guardrail
enum
autonomous · notify · approval_required
domain_id
string — d_ prefix
Organizational domain this item belongs to
project_id
string | null — p_ prefix
Project grouping within a domain
tags
string[] | null
Arbitrary labels for filtering
dependencies
string[] | null
Task IDs this item depends on
metadata
JSON | null
Arbitrary JSON — GitHub issue numbers, links, etc.
context
ContextEntry[] — embedded
Full event timeline. Only present on GET /v1/tasks/:id
artifacts
Artifact[] — embedded
All attached artifacts. Only present on GET /v1/tasks/:id

Context Entry

Append-only event log entry. The persistent memory of the work item — every state change, decision, and observation lives here.

id
string — ctx_ prefix
Unique identifier
task_id
string — t_ prefix
Work item this entry belongs to
type
enum
observation · action_taken · decision · blocker · state_transition · handoff · proposal · approval_requested · approval_received · artifact_created · claim · release
body
string
Content of the entry — what happened
author
string
Agent or user ID who wrote this entry
actor_type
enum
agent · human · system
created_at
ISO 8601 UTC
When this entry was created

Artifact

First-class output objects. Not buried in notes — queryable, linkable, part of the structured record.

id
string — art_ prefix
Unique identifier
task_id
string — t_ prefix
Work item this artifact is attached to
type
enum
file · branch · commit · pull_request · patch · plan · doc · terminal_output
title
string | null
Human-readable label
uri
string | null
URL or file path — use for branch, PR, commit, file
body
string | null
Inline content — use for patch text, plan markdown, terminal output
created_by
string
Agent or user ID who created the artifact
metadata
JSON | null
e.g. pr_number, base_branch, file_size
created_at
ISO 8601 UTC
Creation timestamp

Domain, Project, Agent

Domain
id
d_ prefix
name
string
e.g. "backend", "infra"
default_guardrail
enum
autonomous · notify · approval_required
Project
id
p_ prefix
name
string
domain_id
FK → Domain
description
string | null
Agent
id
free-form string
e.g. "claude-code"
name
string
Display name
type
string
e.g. "coding-agent", "generic"
capabilities
JSON | null
last_seen
ISO 8601 UTC
Updated on every auth'd request
05

Behavioral Guide

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.

Session Start

01

Check in

Call threadron_checkin at the start of every session. It returns in-progress, pending, and blocked work in one call. This is your orientation.

MCP threadron_checkin()
02

Resume in-progress work first

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.

03

Claim before starting anything

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.

The Update Pattern

Use this pattern at every meaningful step while working. Always log context first, then update state.

The pattern // 1. Log what happened (the WHY) threadron_add_context(task_id, type: "observation", body: "Found root cause at pool.ts:47...") // 2. Update structured state (the WHAT) threadron_update_state(task_id, current_state: "Root cause found. Implementing fix.", next_action: "Write tests, open PR.")
SituationContext typeState 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

Session End / Pausing

Before the session ends or when switching to other work, leave a clean handoff:

01

Summarize the session

Call threadron_add_context(type: "action_taken", body: "Pausing. [Summary of what was done...]")

02

Set clean state for the next session

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.

03

Release the claim

Call threadron_release. This makes the item available for other agents. If the work is complete, set status: "completed" first.

Multi-Agent Coordination

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.

Guardrail Handling

Check the task's guardrail field (falls back to domain default_guardrail) before acting:

LevelBehavior
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.

Key Principles

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.

First-Run Onboarding

On first connection, check GET /v1/config/onboarding_complete. If missing or false, run the setup flow:

Setup flow // 1. Register the agent POST /v1/agents { "id": "claude-code", "name": "Claude Code", "type": "coding-agent", "capabilities": [...] } // 2. Ask user for domains, then create each one POST /v1/domains { "name": "backend", "default_guardrail": "autonomous" } // 3. Set approval behavior preference POST /v1/config { "key": "approval_behavior", "value": "collect_and_summarize" } // 4. Mark setup complete POST /v1/config { "key": "onboarding_complete", "value": true }