Skip to main content
Glama

Run five or ten coding agents on one repository and they edit the same files, rename things others depend on, and build both sides of an interface to different shapes. Tirith is a small daemon they all talk to: an agent claims files before editing, gets the notices, contracts, decisions, and notes for those files back with the claim, and publishes the shape of an interface before either side implements it.

It works with anything that speaks MCP, over stdio or HTTP: Claude Code, Cursor, Codex, LangGraph, CrewAI, or a plain script.

It also remembers. Agents leave notes scoped to repository paths, so what one agent learned about a file reaches the next agent that claims it. Tirith stores no conversation history and no embeddings.

Status: v1.1.0. Every primitive, the CLI, persistence, and the dashboard are built and tested. v1 shipped against the definition in ADR-0013; tool schemas now follow semantic versioning.

Install

macOS and Linux:

curl -LsSf https://eabz.github.io/tirith/install.sh | sh

Windows (PowerShell):

irm https://eabz.github.io/tirith/install.ps1 | iex

With cargo (the package is tirith-mcp, the binary is tirith):

cargo install tirith-mcp

Already installed? tirith update replaces the binary in place with the latest release. Prebuilt binaries for macOS, Linux, and Windows on x86_64 and ARM64 are on the releases page; every option is in docs/1-about/05-installation.md.

Listed in the MCP Registry: mcp-name: io.github.eabz/tirith.

Related MCP server: LLM Bus

Quick start

Register tirith stdio with your client, the same way as any other stdio MCP server. It starts the repository's daemon the first time a session needs it, replaces a daemon of another version, and proxies to it after that; nothing has to be started by hand.

Client

Setup

Claude Code

claude mcp add tirith -- tirith stdio

Cursor

.cursor/mcp.json: { "mcpServers": { "tirith": { "command": "tirith", "args": ["stdio"] } } }

Codex

codex mcp add tirith -- tirith stdio

LangGraph, CrewAI, curl

connect over HTTP, see docs/2-examples/02-client-setup.md

The daemon serves MCP at http://127.0.0.1:7477/mcp and a live dashboard at http://127.0.0.1:7477/. State is written to .tirith/ in your repository: contracts, notices, decisions, and memory notes are meant to be committed; .tirith/runtime/ (claims, tasks, messages) is gitignored by a .gitignore Tirith writes itself.

Every agent passes a stable agent name with each call. That is the only convention it has to follow.

What it does

Primitive

Tools

Purpose

Claims

claim, release, renew, claims_list

Lease files or directories before editing. Overlaps are refused with the owner, reason, and expiry, or waited out server-side with wait_secs. Leases expire if the agent dies, and the agent is told on its next call.

Task board

task_create, task_pull, task_update, task_list

Tasks with priority, owner, and dependencies. Agents pull the next unblocked task, skipping tasks another agent holds, and can wait server-side for one with wait_secs; a task whose owner goes silent returns to the board.

Contracts

contract_publish, contract_get, contract_list

Interface shapes published and versioned before implementation. A new version notifies its consumers automatically.

Change notices

notice_publish, notice_list

"Renamed X to Y, these paths are affected." Dependents get them in the brief that comes back with a claim, once each.

Decisions log

decision_record, decision_list

Settled choices with rationale, so nothing is decided twice.

Memory notes

memory_write, memory_read, memory_search, memory_delete

Lessons, traps, and handoffs scoped to repository paths. Committed Markdown, searchable, and delivered to whoever claims the paths a note is about.

Messages

message_send, message_list

Short notes between agents, delivered on the recipient's next call, so any MCP client can take part. Runtime only.

Status

status

Counts, persistence and load problems; verbose adds who holds what.

Twenty-two tools. Every result is JSON with a status field, lists are paged, and any result may carry lost (a lease that ended) or inbox (messages waiting). The full reference, the single source of truth for tool schemas, is docs/1-about/04-primitives.md.

Example

Two agents, one directory. The second is refused with enough information to decide what to do next:

tirith claim --agent alice --reason "refactor session handling" src/auth/
# ok       alice  src/auth  expires 04:14:34Z

tirith claim --agent bob --reason "fix login redirect" src/auth/login.rs
# conflict src/auth/login.rs overlaps src/auth (alice: "refactor session handling", expires 04:14:34Z)

A note left for whoever edits a path next. Alice writes it once; it comes back on Bob's claim without anyone searching, as an excerpt, never a body:

tirith memory write --agent alice "Session ids are opaque" -k gotcha --path src/auth/ <<'NOTE'
Tokens are opaque strings. Compare them, never parse them.
NOTE

tirith release --agent alice
tirith claim --agent bob --reason "fix login redirect" src/auth/login.rs
# ok       bob  src/auth/login.rs  expires 04:14:34Z
# memory:
#   session-ids-are-opaque gotcha   04:04:34Z  paths src/auth  Session ids are opaque: Tokens are opaque strings. Compare them, never parse them.

The full walkthrough, with contracts, notices, and the same calls over raw MCP, is docs/2-examples/01-two-agents-demo.md; the script is examples/demo.sh.

CLI

Every tool has a subcommand; the CLI uses the same MCP path agents do.

tirith serve                               # run the repo's daemon by hand
tirith stdio                               # per-session shim clients spawn; starts the daemon if needed
tirith update                              # replace the binary with the latest release
tirith status                              # counts, and who holds what
tirith claim | release | renew | claims
tirith task     create | pull | update | list
tirith contract publish | get | list
tirith notice   publish | list
tirith decision record | list
tirith memory   write | read | search | delete   # body from --body, --file, or stdin
tirith message  send | list                # talk to other agents; the inbox shows on any result
tirith lead log                            # the swarm lead and its policy's decisions
tirith lead human                          # items waiting for you, most agents blocked first
tirith lead human done <id> [--reply TEXT] # answer one; the reply reaches its sender
tirith tray                                # macOS only: menu bar icon listing every daemon
tirith tools                               # list tools with descriptions
tirith call <tool> '<json>'                # call any tool directly

--agent sets your name, --json prints the raw result, and non-ok outcomes exit with status 1.

Swarm lead and escalations

The session that spawns other agents claims the reserved path .tirith/lead and becomes the swarm lead; status and the dashboard show who holds it. The daemon then handles routine escalations with fixed rules, without spending an LLM turn:

  • What escalates: a task set to blocked (its note is the reason), or the third refusal of the same claim within 360 s. A message to the lead is never an escalation.

  • Where it goes: while there is a lead, to the lead's inbox as a message from tirith, tagged "may need the human" when it mentions credentials, permissions, spending, or destructive steps. Nothing reaches you on its own: the lead relays what needs you with message_send to human, written for you. While there is no lead, escalations go to your queue.

  • Your queue: the dashboard's "Needs you" list, tirith lead human, /api/human on the dashboard port, and the macOS tray, which lists each item's sender and first line and notifies you of new ones. Answer with the dashboard's Done button or tirith lead human done <id> --reply "..."; the reply reaches the sender as a message from human.

Claim grants, refusals, waits, releases and lease ends, notice pushes, and escalations are appended to the lead decision log: tirith lead log, or /api/lead on the dashboard port. Design: ADR-0027; per tool: 04-primitives.md.

Documentation

Section

Contents

1-about

Purpose, architecture, project structure, tool reference, installation

2-examples

The demo and client setup for every supported framework

3-tests

Testing strategy

4-style

Rust rules and their sources, git conventions

5-decisions

Architecture decision records

6-agent-workflow

How agents work on this repo: Serena, memory, Tirith on itself

7-release

Release process and version bumping

index.html

The landing page at eabz.github.io/tirith

Contributing

Coding agents must read AGENTS.md first. This repository is coordinated with Tirith itself: a daemon runs for the repo and agents claim files through it before editing.

License

MIT

Available Tools

23 tools
claimA

Lease repo paths to yourself before editing them, atomically: every path becomes yours or none does. A directory covers its contents, and re-claiming a path you hold renews it. ok carries a brief of the unread notices, contracts, decisions and memory notes for those paths, and marks the notices shown as seen: read it before editing. conflict lists each overlapping lease; do not edit, or pass wait_secs so the daemon waits for the paths instead of you retrying. To see who holds a path without taking it use claims_list; to extend leases use renew.

ParametersJSON Schema
NameRequiredDescriptionDefault
agentYesYour stable agent name.
briefNoAttach the brief. Default true.
pathsYesRepo-relative files or directories. A directory covers everything beneath it.
reasonYesWhy you need these paths; shown to any agent that is refused.
ttl_secsNoLease length in seconds. Default 600, max 3600.
wait_secsNoOn conflict, wait up to this many seconds (max 120) for the paths to free.

Output Schema

ParametersJSON Schema
NameRequiredDescription
moreNoPer brief section, how many matching rows were left out; page with the list tools when not zero.
memoryNoBrief: up to 5 memory notes about these paths, as digests with an excerpt. Bodies via memory_read.
statusYesok: every path is yours. conflict: nothing was claimed. cancelled: a wait whose caller left. invalid: bad input.
messageNoHuman-readable detail, on most outcomes other than ok.
noticesNoBrief: up to 5 unread notices for these paths (id, kind, summary, by). Now marked seen by you.
claim_idNoThe new lease; null when every path was only renewed.
conflictsNoOn conflict, one per overlapping path: path, overlaps, owner, reason, expires_at.
contractsNoBrief: up to 5 contracts these paths consume (name, version, kind). Bodies via contract_get.
decisionsNoBrief: up to 5 decisions affecting these paths (id, title).
new_pathsNoPaths claimed by this call.
expires_atNoRFC 3339 end of the lease unless renewed.
renewed_pathsNoPaths you already held, renewed.
absorbed_pathsNoPaths you held beneath a directory just claimed, folded into it.
previous_ownerNoFor a new path whose lease another agent lost in the last hour: path, owner, reaped_at. It may be half-edited.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Despite the annotation being limited to destructiveHint=false, the description discloses rich behavioral details: atomic all-or-nothing acquisition, directory recursion, renewal on re-claim, the brief's side effect of marking notices as seen, and conflict semantics. This goes far beyond annotation coverage and gives the agent a realistic model of the tool's effects.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but every sentence contributes: atomic semantics, directory behavior, renewal, brief contents and side effects, conflict handling, and explicit alternatives. It is front-loaded with the core action and avoids redundancy with the schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with six parameters and non-trivial concurrency semantics, the description covers the essential behavioral context: atomicity, conflicts, waiting, brief behavior, and alternative tools. The presence of an output schema means return values need not be spelled out, and nothing critical is missing for an agent to invoke this tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description adds meaning beyond the schema by explaining why wait_secs is used (daemon waits for paths instead of retrying), how paths behave with directories, and that re-claiming renews a lease, which enriches the ttl_secs and paths parameters. It does not cover every parameter, but it supplements the schema well.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource ('Lease repo paths to yourself before editing them') and immediately clarifies the atomic scope. It distinguishes itself from siblings by naming claims_list and renew as alternatives, and the lease terminology is unique among the sibling tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states when to use this tool ('before editing them'), when not to edit on conflict, and when to use wait_secs. It names the alternative tools for non-taking inspection (claims_list) and extension (renew), giving an agent clear routing guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

claims_listA
Read-only

List live leases: by default yours plus any lease overlapping path, which is what a conflict check needs; all=true lists the whole board. Use before claim to see who holds a path and until when; for counts and daemon health use status. Expired leases are never listed. Newest first, 20 rows per page; pass next_before as before for older rows.

ParametersJSON Schema
NameRequiredDescriptionDefault
allNoList every live claim, not just yours and those overlapping `path`.
pathNoAlso include claims overlapping this path, whoever holds them.
agentYesYour stable agent name.
limitNoRows to return (default 20, max 200), newest first.
beforeNoOnly claims older than this cursor: an RFC 3339 timestamp or a previous response's `next_before`.

Output Schema

ParametersJSON Schema
NameRequiredDescription
countNoRows in this response.
totalNoRows that matched, across all pages.
claimsNoid, owner, paths, reason, claimed_at, expires_at, ttl_secs. Expired claims are never listed.
statusYesok. invalid: bad input.
messageNoHuman-readable detail, on most outcomes other than ok.
truncatedNoTrue when older rows were left out.
next_beforeNoPresent when truncated: pass it back as before for the next older page.

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the readOnlyHint annotation, the description discloses important behavior: expired leases are never listed, newer leases come first, pagination defaults to 20 rows, and next_before drives older-result pagination. This gives the agent a clear model of what the call returns and its limits.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four dense sentences carry purpose, scope, usage guidance, exclusions, ordering, and pagination with zero filler. The most important scoping information is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only listing tool with full schema coverage and an output schema, this description covers selection criteria, sibling routing, exclusions, ordering, and pagination. Nothing essential for correct invocation is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, but the description adds real semantic value by explaining the default behavior of path and all, the meaning of all=true, and how before consumes next_before for pagination. It connects parameters to behavior rather than repeating schema names.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: 'List live leases' with precise default scope ('yours plus any lease overlapping path') and the conflict-check purpose. It distinguishes itself from siblings like claim and status, so an agent can tell it apart without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes usage: 'Use before claim to see who holds a path and until when; for counts and daemon health use status.' This gives both when-to-use and an alternative, leaving nothing to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

contract_getA
Read-only

Fetch one contract in full by name, id or unique id prefix: its current shape and every earlier version. Use when a brief or contract_list names a contract you consume; to find contracts by path or kind use contract_list. not_found if there is none, and an ambiguous prefix is invalid.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesThe contract's name, its id, or a unique prefix of the id.
agentYesYour stable agent name.

Output Schema

ParametersJSON Schema
NameRequiredDescription
statusYesok. not_found: no such contract. invalid: an ambiguous id prefix.
messageNoHuman-readable detail, on most outcomes other than ok.
contractNoIn full: id, name, kind, consumers, current (version, shape, notes, published_by, published_at), and history, oldest first.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, and the description consistently describes a read operation, so there is no contradiction. It adds useful behavioral context: not_found when no contract exists and invalid when the prefix is ambiguous, plus the fact that all earlier versions are returned.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with no wasted words. The core action and scope are front-loaded, followed by usage guidance and error semantics. Highly efficient.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers when to use, how to look up, what is returned, and key error conditions. With an output schema present and readOnlyHint annotation, an agent has everything needed to invoke this tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents both parameters. The description adds context about unique prefix validity and lookup semantics, but the parameter meanings are already well covered by the input schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: 'Fetch one contract in full' by name, id, or unique prefix. It explicitly differentiates itself from contract_list, which finds contracts by path or kind, so an agent can immediately tell when this tool applies.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says when to use: 'when a brief or contract_list names a contract you consume.' It also names the alternative for different lookup needs and documents the failure mode for ambiguous prefixes, leaving little to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

contract_listA
Read-only

List contracts, filtered by a consumer path or by kind, most recently published first. Use to find what a path depends on when you are not claiming it, since a claim's brief already lists them; shapes come from contract_get. Rows are compact, 20 rows per page; pass next_before as before for older rows.

ParametersJSON Schema
NameRequiredDescriptionDefault
kindNoOnly contracts of this kind.
pathNoOnly contracts whose consumers overlap this path.
agentYesYour stable agent name.
limitNoRows to return (default 20, max 200), most recently published first.
beforeNoOnly contracts published before this cursor: an RFC 3339 timestamp or a previous response's `next_before`.

Output Schema

ParametersJSON Schema
NameRequiredDescription
countNoRows in this response.
totalNoRows that matched, across all pages.
statusYesok. invalid: bad input.
messageNoHuman-readable detail, on most outcomes other than ok.
contractsNoMost recently published first, compact: id, name, kind, consumers, current version. Shapes via contract_get.
truncatedNoTrue when older rows were left out.
next_beforeNoPresent when truncated: pass it back as before for the next older page.

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, and the description adds useful behavioral details: pagination (20 rows per page, pass next_before as before for older rows) and ordering. No contradiction with the read-only hint.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences front-load the core action and filters, then add usage context and pagination. 'Rows are compact' is slightly vague, but overall every sentence contributes and there is no fluff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers filtering, ordering, pagination, and sibling alternatives. With an output schema present and read-only annotations, an agent has enough to select and call this tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description reinforces path/kind filtering and cursor usage, but it does not add much semantic meaning beyond what the schema already documents for each parameter.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb and resource ('List contracts') and names the two filter dimensions ('consumer path or by kind') plus the sort order. It also distinguishes itself from contract_get by explicitly assigning shape retrieval to that sibling.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It says when to use the tool ('when you are not claiming it') and gives the relevant alternative: a claim's brief already lists dependencies, and shapes come from contract_get. This is clear routing to alternatives without relying on inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

contract_publishA

Publish the shape of an interface (an endpoint, function, type, event or CLI) before either side implements it, with the paths that will consume it. Publishing an existing name creates a new version and sends its consumers a change notice by itself, so do not also call notice_publish. Omitting consumers on a republish keeps the list, and expected_version refuses the write with conflict if another agent published first. To read contracts use contract_get or contract_list.

ParametersJSON Schema
NameRequiredDescriptionDefault
kindYesOne of `http`, `function`, `type`, `event`, `cli`, `other`.
nameYesUnique contract name, for example `POST /api/sessions` or `State::claim`.
agentYesYour stable agent name.
notesNoFree-text notes stored with this version.
shapeYesThe interface shape as JSON: signatures, request and response types, errors.
consumersNoPaths expected to depend on this contract.
expected_versionNoRefuse unless the contract is at this version now (0 = absent).

Output Schema

ParametersJSON Schema
NameRequiredDescription
statusYesok. conflict: expected_version was set and the contract is at another version. invalid: bad input.
messageNoHuman-readable detail, on most outcomes other than ok.
contractNoid, name, kind, consumers, current (version, shape, notes, published_by, published_at), history.
notice_idNoThe change notice emitted to consumers of a republished contract.
published_byNoOn conflict: who published that version.
current_versionNoOn conflict: the version the contract is at.
previous_versionNoThe version this one replaced; absent or null on a first publish.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only provide destructiveHint=false, so the description carries the burden and does well: it discloses that republishing an existing name creates a new version, automatically sends change notices to consumers, preserves the consumer list when omitted, and refuses writes via expected_version on concurrent publication.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three dense sentences with no filler. The primary action is front-loaded, and each clause adds a distinct behavioral or usage fact: side effects, caller exclusions, preservation semantics, concurrency guard, and read alternatives.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 7-parameter publish tool with an output schema, the description covers the key agent-facing concerns: side effects, duplicate-notice prevention, concurrency conflict, optional consumer behavior, and where to read contracts. Nothing essential for correct invocation is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description adds real value beyond the schema by explaining the semantics of consumers ('omitting keeps the list') and expected_version ('refuses the write with conflict if another agent published first'), elevating it above a mere schema restatement.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: publish the shape of an interface (endpoint, function, type, event, CLI) before implementation, with consumer paths. It clearly differentiates from siblings by naming contract_get, contract_list, and notice_publish as distinct tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives explicit when-to-use context ('before either side implements it'), explicitly warns not to also call notice_publish, and directs read operations to contract_get or contract_list. It also explains republish and conflict semantics, so an agent knows exactly when to use this tool and when not to.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

decision_listA
Read-only

List recorded decisions, filtered by an affected path or a case-insensitive text query over title, decision and rationale, newest first. Use before decision_record so nothing is decided twice; a claim's brief already carries the decisions for the paths it claims. 20 rows per page; pass next_before as before for older rows.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathNoOnly decisions affecting this path.
agentYesYour stable agent name.
limitNoRows to return (default 20, max 200), newest first.
queryNoCase-insensitive text to search for.
beforeNoOnly decisions recorded before this cursor: an RFC 3339 timestamp or a previous response's `next_before`.

Output Schema

ParametersJSON Schema
NameRequiredDescription
countNoRows in this response.
totalNoRows that matched, across all pages.
statusYesok. invalid: bad input.
messageNoHuman-readable detail, on most outcomes other than ok.
decisionsNoNewest first: id, title, decision, rationale, alternatives, affects_paths, recorded_by, recorded_at.
truncatedNoTrue when older rows were left out.
next_beforeNoPresent when truncated: pass it back as before for the next older page.

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The readOnlyHint annotation already marks it as safe/read-only, and the description adds meaningful behavioral detail beyond that: case-insensitive search scope, newest-first ordering, 20-row default page size, and how to retrieve older rows using next_before. This gives the agent a solid model of the tool's runtime behavior without contradicting the annotation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences deliver the core capability, the primary use case and alternative, and pagination behavior with no filler. Key information is front-loaded, and every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a filtered, read-only list tool, nothing essential is missing: it explains what is listed, how to filter, how results are ordered, how pagination works, and when to prefer it over decision_record. The output schema covers return values, and the annotations cover the read-only safety profile.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds value by clarifying that query searches title, decision, and rationale, and by explaining that next_before from a prior response should be passed as before for older pages. This goes beyond the schema's terse descriptions and helps the agent use the parameters correctly.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'List recorded decisions', then states the filtering modes (affected path or case-insensitive query over title, decision, rationale) and ordering (newest first). It also distinguishes itself from the sibling decision_record, so an agent can tell them apart immediately.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives explicit usage direction: 'Use before decision_record so nothing is decided twice', which names the alternative and the condition for using this tool. It also notes that a claim's brief already carries decisions for claimed paths, providing a clear when-not-to-use signal, while pagination instructions further clarify how to invoke it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

decision_recordA

Record a settled project choice with its rationale, the alternatives considered and the paths it constrains, so no agent decides it again. It is written as one committed Markdown file under .tirith/decisions/ and appears in the brief of later claims on those paths. Use only once the choice is final; for discussion use message_send, and for lessons about code use memory_write. Returns the decision with its permalink.

ParametersJSON Schema
NameRequiredDescriptionDefault
agentYesYour stable agent name.
titleYesShort title, the line shown in briefs.
decisionYesWhat was decided, stated so it can be followed.
rationaleNoWhy it was decided.
alternativesNoThe alternatives that were considered and rejected.
affects_pathsNoPaths the decision constrains.

Output Schema

ParametersJSON Schema
NameRequiredDescription
statusYesok. invalid: bad input.
messageNoHuman-readable detail, on most outcomes other than ok.
decisionNoid, title, decision, rationale, alternatives, affects_paths, recorded_by, recorded_at, and the permalink of its committed file.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the sparse destructiveHint=false annotation, the description discloses important behavior: it writes 'one committed Markdown file under .tirith/decisions/', makes the record appear 'in the brief of later claims on those paths', and returns 'the decision with its permalink.' This gives the agent a clear model of persistence and side effects.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences cover purpose, storage, side effects, usage timing, alternatives, and return value without redundancy. The core action is front-loaded and every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description is complete for an agent to decide when and how to use the tool: it explains the record's format and location, its effect on future claim briefs, the finality requirement, alternatives, and the return value. Given the rich schema and output schema, nothing essential is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, and each parameter already has a meaningful description, so the baseline is 3. The tool description reinforces the meaning of 'alternatives' and 'affects_paths' but does not add substantive parameter-level semantics beyond what the schema already provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Record a settled project choice with its rationale, the alternatives considered and the paths it constrains.' It clearly states what is recorded and why, and distinguishes itself from siblings by naming message_send and memory_write as alternatives for different situations.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives an explicit condition: 'Use only once the choice is final.' It also names concrete alternatives and their use cases: 'for discussion use message_send, and for lessons about code use memory_write.' This leaves no ambiguity about when to invoke this tool instead of a sibling.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

guideA
Read-only

Explain what Tirith is for and how to work with it: the working loop from claim to release, the rules every reply follows (status, lost, inbox, paging), and which tool each situation calls for. Call it first in a session, or when unsure which tool fits; topic narrows it to one primitive with when to use each of its tools. Returns static guidance only: for the daemon's live state use status.

ParametersJSON Schema
NameRequiredDescriptionDefault
agentNoYour stable agent name, optional here. With it, waiting messages and lost leases ride on the reply as on any other call.
topicNoOne primitive to explain instead of the overview.

Output Schema

ParametersJSON Schema
NameRequiredDescription
loopNoOverview: the working loop, in order.
rulesNoRules every reply follows (overview), or this topic's rules.
toolsNoOverview: topic to tool names. A topic: tool and when to call it, one per tool.
topicNoThe page returned.
statusYesok. invalid: an unknown topic; message lists the valid ones.
topicsNoOverview: every topic guide accepts.
messageNoHuman-readable detail, on most outcomes other than ok.
purposeNoOverview: what Tirith is for.
summaryNoA topic: what the primitive is for.

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=true, and the description reinforces this by stating 'Returns static guidance only', which is valuable behavioral context beyond the annotation. It also clarifies that it does not reflect the daemon's live state, preventing a likely misconception. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences carry the full purpose, usage guidance, and limitation without redundancy. Key information is front-loaded: what the tool does, when to call it, and what it does not provide. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the simple two-parameter schema with an enum, full schema coverage, an output schema, and readOnlyHint annotation, the description is complete. It covers what the tool explains, when to call it, how to narrow the topic, and how it differs from status, so an agent has everything needed to select and invoke it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already documents both parameters. The description adds meaning by explaining that topic 'narrows it to one primitive with when to use each of its tools', which clarifies the purpose of the enum beyond its literal value list. The agent parameter is also given contextual significance in the schema description.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Explain') and resource ('what Tirith is for and how to work with it'), covering the working loop, reply rules, and tool selection. It clearly differentiates itself from status by noting it returns static guidance only, and from the broader sibling tools by positioning itself as the meta-orientation tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit usage guidance is given: 'Call it first in a session, or when unsure which tool fits'. It also explains how to narrow via topic and gives an explicit exclusion: for live daemon state, use status. This leaves little ambiguity about when to invoke this tool versus alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

memory_deleteA
DestructiveIdempotent

Delete one memory note by permalink, id or exact title, permanently: its file is removed and does not return on restart. Use to retract a note that holds a secret or a wrong fact; to correct a note use memory_write, which updates in place. Returns a digest of what was removed; not_found if there is none.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesA permalink, an id, or an exact title.
agentYesYour stable agent name.

Output Schema

ParametersJSON Schema
NameRequiredDescription
statusYesok. not_found: no such note.
messageNoHuman-readable detail, on most outcomes other than ok.
removedNoA digest of the deleted note: permalink, title, kind, paths, tags, updated_at, and a 160-character excerpt.

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint and idempotentHint, but the description adds specific context: 'its file is removed and does not return on restart' and 'Returns a digest of what was removed; not_found if there is none'. This goes beyond the annotations by detailing the permanence and the failure mode, which is valuable for an agent.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, zero fluff. The core purpose is front-loaded ('Delete one memory note...'), followed by usage guidance and return behavior. Every word earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers the tool's purpose, usage vs. alternatives, behavior, and return value. It mentions the output (digest and not_found) which aligns with having an output schema. For a simple delete operation, nothing critical is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema description for 'name' is 'A permalink, an id, or an exact title' and for 'agent' is 'Your stable agent name'. The description does not add extra meaning beyond the schema – it repeats the same identification options. Since schema coverage is 100%, the baseline is 3, and the description provides no additional parameter context.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Delete'), resource ('memory note'), and identification method ('by permalink, id or exact title'). It distinguishes itself from memory_write by clarifying that this is for permanent removal, not correction. This clearly separates it from siblings like memory_write and memory_read.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states when to use this tool: 'to retract a note that holds a secret or a wrong fact'. It also names the alternative for correcting: 'to correct a note use memory_write, which updates in place'. This is clear, actionable guidance on tool selection.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

memory_readA
Read-only

Read one memory note in full by permalink, id or exact title. It is the only tool that returns a note's body; depth 1 to 3 adds the notes linked to it, as digests. Use after memory_search or a claim's brief names the note; to find notes use memory_search. not_found if there is none.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesA permalink, an id, or an exact title.
agentYesYour stable agent name.
depthNoHow many relation hops of related notes to include, 0 to 3.

Output Schema

ParametersJSON Schema
NameRequiredDescription
noteNoThe whole note, body included: id, permalink, title, kind, body, observations, relations, paths, tags, author, updated_by, created_at, updated_at.
statusYesok. not_found: no such note. invalid: depth above 3.
messageNoHuman-readable detail, on most outcomes other than ok.
relatedNoWith depth above 0, at most 20 linked notes as digests: permalink, title, kind, paths, tags, updated_at, and a 160-character excerpt.

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, so the safety profile is covered. The description adds value beyond that by disclosing the depth behavior ('depth 1 to 3 adds the notes linked to it, as digests') and the error case ('not_found if there is none'), which are genuine behavioral traits not derivable from the annotations or schema alone.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four sentences with the core action front-loaded in sentence one, followed by scoping, usage routing, and error behavior. Each sentence earns its place; slightly denser than strictly necessary but no wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Complete for a read tool: output schema covers return values, annotations cover safety, all parameters are documented, the usage sequence is specified, the depth semantics are clarified, and the not_found failure mode is disclosed. Nothing an agent needs to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline of 3 applies — the schema already documents name, agent, and depth. The description adds a small increment by clarifying that depth returns linked notes 'as digests,' but it largely restates the name parameter's meaning in the first sentence.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Read one memory note in full') plus the identification methods (permalink, id, or exact title). It also differentiates from siblings by asserting 'It is the only tool that returns a note's body,' which cleanly separates it from memory_search.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly names the sequence and the alternative: 'Use after memory_search or a claim's brief names the note; to find notes use memory_search.' This tells the agent exactly when this tool is appropriate versus its sibling, leaving nothing to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

memory_writeA
Idempotent

Save a durable note about repository paths (a lesson, trap, handoff or research) as committed Markdown; the next agent that claims those paths gets its excerpt in the brief. A title that already exists updates that note in place, and permalink targets one explicitly. Pass the updated_at you read as if_updated_at so a concurrent edit returns conflict instead of being overwritten. Not for settled choices (decision_record) or talk between agents (message_send).

ParametersJSON Schema
NameRequiredDescriptionDefault
bodyYesThe note itself, as Markdown.
kindNoOne of `fact`, `lesson`, `gotcha`, `handoff`, `research`, `decision`, `note` (the default).
tagsNoTags for filtering; lowercased, and a leading `#` is dropped.
agentYesYour stable agent name.
pathsNoRepo-relative paths this note is about.
titleYesShort title. Becomes the permalink the first time.
permalinkNoOverwrite this note instead of matching on the title.
if_updated_atNoRFC 3339 `updated_at` from a read; refused if the note changed since.

Output Schema

ParametersJSON Schema
NameRequiredDescription
noteNoThe note as stored: id, permalink, title, kind, body, observations, relations, paths, tags, author, updated_by, created_at, updated_at.
statusYesok. conflict: if_updated_at was set and the note changed since. not_found: an explicit permalink that does not exist. invalid: bad kind or input.
createdNoTrue for a new note, false when an existing title or permalink was updated.
messageNoHuman-readable detail, on most outcomes other than ok.
permalinkNoOn conflict: the note that changed.
updated_atNoOn conflict: its real updated_at; read again and retry.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the idempotentHint and destructiveHint annotations, the description discloses substantive behavior: notes are committed Markdown, the next agent claiming the associated paths receives the excerpt, matching titles update in place, permalink allows explicit targeting, and if_updated_at prevents overwriting concurrent edits. This is rich, high-value behavioral context that annotations alone do not provide.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is three dense sentences with no filler. The first sentence front-loads the core purpose and scope, the second explains update and concurrency behavior, and the third gives exclusions. Every sentence earns its place, making the description easy to parse quickly.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with 8 parameters, the description covers the essential context: what kind of content to store, how it is persisted, how future agents consume it, how to update versus target, how to handle concurrency, and which sibling tools are not appropriate. The output schema covers return values, so the description does not need to repeat them. Nothing critical is missing for an agent to call this tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds real semantic value beyond the schema: it explains that an existing title updates the note in place, that permalink targets a specific note, and that if_updated_at should carry the read value to get conflict detection instead of silent overwrites. This enhances the agent's understanding of title, permalink, and if_updated_at beyond their schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'Save a durable note about repository paths ... as committed Markdown.' It clearly differentiates from siblings by explicitly naming decision_record and message_send as not-this-tool. An agent can immediately understand what memory_write accomplishes and how it differs from nearby alternatives.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit when-to-use context ('a lesson, trap, handoff or research') and explicit when-not-to-use alternatives ('Not for settled choices (decision_record) or talk between agents (message_send)'). It also provides operational guidance about updating existing titles and using if_updated_at for concurrency, leaving little to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

message_listA
Read-only

List your own conversations, sent and received, newest first; filter by the other agent (with), since a time, or unread messages to you. New messages already arrive as inbox on every reply, so use this for history, not to poll. with=human shows the human queue thread. 20 rows per page; pass next_before as before for older rows.

ParametersJSON Schema
NameRequiredDescriptionDefault
withNoOnly the conversation with this agent.
agentYesYour stable agent name.
limitNoRows to return; default 20, max 200.
sinceNoOnly messages sent at or after this RFC 3339 instant.
beforeNoOnly messages older than this cursor: an RFC 3339 timestamp or a previous response's `next_before`.
unreadNoOnly messages to you that you have not received yet.

Output Schema

ParametersJSON Schema
NameRequiredDescription
countNoRows in this response.
totalNoRows that matched, across all pages.
statusYesok. invalid: bad input.
messageNoHuman-readable detail, on most outcomes other than ok.
messagesNoNewest first, sent or received by you: id, from, to, text, reply_to, paths, at.
truncatedNoTrue when older rows were left out.
next_beforeNoPresent when truncated: pass it back as before for the next older page.

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true; the description adds meaningful behavior beyond that: newest-first ordering, the inbox-vs-history nuance, the human-queue special case, and 20-row pagination with next_before. It stops short of describing the response shape, but the output schema covers that.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences front-load the core behavior and filters, then provide usage guidance and pagination. Every clause earns its place; there is no repetition of the schema or filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only list operation with a rich output schema and 100% parameter coverage, the description is sufficient: it covers filtering, ordering, pagination, the human-queue special case, and the polling caveat. An agent has everything needed to call the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description adds valuable extra semantics: with=human maps to the human queue thread, before accepts a previous response's next_before, and the default page size is 20. These details go beyond the schema's field descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a precise verb and resource: 'List your own conversations, sent and received, newest first'. It specifies scope, ordering, and filter dimensions, clearly distinguishing it from siblings like message_send, claims_list, and task_list.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives explicit usage direction: 'use this for history, not to poll', explaining that new messages already arrive as inbox on every reply. It also documents the special human-queue case ('with=human shows the human queue thread') and the pagination workflow.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

message_sendA

Send a short message to one agent by name, to every agent active in the last hour with *, or to the human queue with human. It is delivered once, as inbox on the recipient's next call of any tool, and reply_to threads an answer. Use for coordination talk; not for lasting knowledge (memory_write, decision_record) or for code changes others must react to (notice_publish). Messages are dropped after 24 hours.

ParametersJSON Schema
NameRequiredDescriptionDefault
toYesThe recipient's agent name, `*` for every agent active in the last hour, or `human` for the human queue.
textYesThe message, at most 1000 characters.
agentYesYour stable agent name.
pathsNoPaths the message is about.
reply_toNoId, or a unique prefix, of the message this one answers.

Output Schema

ParametersJSON Schema
NameRequiredDescription
statusYesok. not_found: an unknown reply_to. invalid: empty or over-long text, a bad recipient, or agent human.
messageNoOn ok, the message as sent: id, from, to, text, reply_to, paths, at; audience lists the recipients of a broadcast. On any other outcome, why, as text.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses key behavioral traits beyond the annotations: messages are delivered only once, appear as inbox on the recipient's next tool call, support reply_to threading, and are dropped after 24 hours. This goes well beyond the sparse destructiveHint annotation and gives an accurate model of side effects.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and well-structured: first the core send action and recipient types, then delivery semantics, then explicit usage boundaries, then retention. Every sentence adds necessary information without repetition or filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with 5 parameters and an output schema, the description covers the important behavioral context: who can receive, how delivery works, how replies thread, when to use it, and what it is not for. The remaining parameter details are already fully documented in the schema, so nothing critical is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema already covers all parameters with descriptions, so the baseline is 3. The tool description adds extra meaning by explaining the special recipient values ('*', 'human'), the threading behavior of reply_to, and the overall 'short message' intent, which clarifies how parameters should be used.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's function: sending a short message to one agent, all active agents, or the human queue. It differentiates from siblings by explicitly naming alternatives like memory_write, decision_record, and notice_publish, and by describing the delivery mechanism.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly says 'Use for coordination talk; not for lasting knowledge (memory_write, decision_record) or for code changes others must react to (notice_publish).' This gives an agent clear when-to-use and when-not-to-use guidance, naming the exact sibling tools to use instead.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

notice_listA

List change notices for a path, since a time, or only those you have not been shown (unread=true), newest first. unread without path is scoped to the paths you hold, and all=true looks beyond them. Listing unread notices marks them seen by you, durably, so they do not come back. A claim's brief already delivers the unread notices for the paths it claims; use this for other paths or older pages. 20 rows per page; pass next_before as before for older rows.

ParametersJSON Schema
NameRequiredDescriptionDefault
allNoWith `unread`, look beyond the paths you hold.
pathNoOnly notices affecting this path.
agentYesYour stable agent name.
limitNoRows to return (default 20, max 200), newest first.
sinceNoOnly notices published at or after this RFC 3339 timestamp.
beforeNoOnly notices published before this cursor: an RFC 3339 timestamp or a previous response's `next_before`.
unreadNoOnly notices you neither published nor were already shown. Without `path` or `all`, this is scoped to the paths you currently hold.

Output Schema

ParametersJSON Schema
NameRequiredDescription
countNoRows in this response.
totalNoRows that matched, across all pages.
statusYesok, with zero rows and a message when unread is scoped to paths and you hold none. invalid: bad input.
messageNoHuman-readable detail, on most outcomes other than ok.
noticesNoNewest first: id, kind, summary, from, to, affected_paths, published_by, published_at. Rows returned for unread=true are now marked seen by you.
truncatedNoTrue when older rows were left out.
next_beforeNoPresent when truncated: pass it back as before for the next older page.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses a critical side effect beyond the annotations: 'Listing unread notices marks them seen by you, durably, so they do not come back.' It also reveals pagination behavior with 20-row pages and the next_before cursor semantics, which annotations do not cover. No contradiction with destructiveHint=false exists since marking-as-read is not destructive.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is tight, front-loaded with purpose, then scope, side effect, alternative routing, and pagination. Every sentence adds distinct value with no filler or redundancy. It is dense but immediately scannable.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with 7 parameters and no output schema details in the description, this is complete: it covers what the tool does, how unread scoping works, the side effect of reading, when to use an alternative, and pagination mechanics. The existing output schema covers return shape, and the agent parameter is explained in the schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds cross-parameter meaning beyond the schema: unread without path is scoped to held paths, all=true expands beyond them, and next_before from a prior response should be passed as before for older pages. This is substantive supplementary semantics beyond the individual parameter descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource—'List change notices'—and immediately distinguishes filtering dimensions: path, since time, and unread status, with ordering. It also contrasts with the claim brief and notice_publish sibling, so an agent can identify this as the retrieval tool rather than a mutation tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly tells the agent when NOT to use this tool: 'A claim's brief already delivers the unread notices for the paths it claims; use this for other paths or older pages.' This is clear routing guidance, and the unread/all scoping rules further clarify which invocation is appropriate.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

notice_publishA

Announce a change other files must react to: a rename, signature change, removal, move or behavior change, with from, to and the affected_paths. Use after changing something used outside the paths you claimed; not for interface shapes, which contract_publish versions and announces itself. Every other agent holding an affected path gets it in its inbox at once, and the rest see it in the brief of their next claim there.

ParametersJSON Schema
NameRequiredDescriptionDefault
toNoThe new name, location, or shape.
fromNoThe old name, location, or shape.
kindYesOne of `rename`, `signature`, `removed`, `moved`, `behavior`.
agentYesYour stable agent name.
summaryYesOne-line summary, for example `renamed session_id to token`.
contract_idNoRelated contract id, if any.
affected_pathsYesPaths whose code must react.

Output Schema

ParametersJSON Schema
NameRequiredDescription
noticeNoid, kind, summary, from, to, affected_paths, contract_id, published_by, published_at.
statusYesok. not_found: an unknown contract_id. invalid: bad kind or input.
messageNoHuman-readable detail, on most outcomes other than ok.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With only destructiveHint=false in the annotations, the description carries most of the behavioral disclosure burden. It reveals the side effects: 'Every other agent holding an affected path gets it in its inbox at once' and the rest see it in the brief of their next claim. This lets an agent anticipate the reach of publishing a notice.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences with the purpose first, usage second, and consequence third; no filler or repetition. The longer third sentence earns its place by describing the delivery mechanism.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 7-parameter tool with 4 required parameters, an output schema exists and every parameter is documented in the schema. The description supplies the remaining usage rule and behavioral consequences, so nothing essential seems missing for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the structured fields already define kind, from/to, and affected_paths. The description only renames these ('with from, to and the affected_paths') and does not add format, edge-case, or constraint details beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and object: 'Announce a change other files must react to' and enumerates concrete change kinds ('rename, signature change, removal, move or behavior change'). It also explicitly distances itself from interface-shape changes, which are 'contract_publish' territory, so it is distinguishable from its sibling tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It states exactly when to use it: 'Use after changing something used outside the paths you claimed.' It also gives a clear exclusion: 'not for interface shapes, which contract_publish versions and announces itself,' pointing to the alternative sibling.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

releaseA
Idempotent

Give up leases so other agents can claim the paths; omit paths to release everything you hold. Use when you finish editing, not to extend time (renew) or to inspect (claims_list). Paths are matched exactly: releasing a file does not release a file#Symbol anchor inside it. not_found if you do not hold a named path, and then nothing is released.

ParametersJSON Schema
NameRequiredDescriptionDefault
agentYesYour stable agent name.
pathsNoPaths to release. Omit to release everything you hold.

Output Schema

ParametersJSON Schema
NameRequiredDescription
agentNoThe caller.
statusYesok, or not_found when you do not hold a named path (nothing is released). invalid: bad input.
messageNoHuman-readable detail, on most outcomes other than ok.
releasedNoThe paths released.

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare idempotentHint=true and destructiveHint=false, and the description does not contradict them. It adds useful behavioral detail beyond annotations: exact path matching, the file#Symbol anchor nuance, and atomic not_found behavior where nothing is released. This is strong supplementary transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact at three sentences with no filler, and it front-loads the core purpose. The structure could be slightly smoother, but every sentence contributes necessary information about behavior, usage, or edge cases.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given only two parameters, a full-coverage schema, and a provided output schema, the description covers purpose, usage, alternatives, exact matching, error behavior, and release-all semantics. Nothing essential appears to be missing for an agent to invoke the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description adds meaningful semantics beyond the schema: omitting paths releases everything held, path matching is exact, and releasing a file does not release embedded anchors. These details help the agent use the paths parameter correctly.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Give up leases so other agents can claim the paths', and clarifies the omit-paths release-all behavior. It also distinguishes this tool from siblings like renew and claims_list, so an agent can tell it apart without inspecting schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly states when to use the tool ('Use when you finish editing') and what not to use it for ('not to extend time (renew) or to inspect (claims_list)'). This gives clear, actionable routing guidance with named alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

renewA
Idempotent

Extend every lease you hold by its original TTL and restart the four-TTL age limit that ends a lease however active you are. Needed only during long work with no other call, because any tool call already renews; to take new paths use claim. Returns how many leases were renewed and the latest expiry; not_found when you hold none.

ParametersJSON Schema
NameRequiredDescriptionDefault
agentYesYour stable agent name.

Output Schema

ParametersJSON Schema
NameRequiredDescription
agentNoThe caller.
countNoLeases renewed.
statusYesok. not_found: you hold no claims. invalid: bad input.
messageNoHuman-readable detail, on most outcomes other than ok.
expires_atNoRFC 3339 latest expiry among the renewed leases.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare idempotentHint=true and destructiveHint=false, and the description adds meaningful behavioral detail: the TTL extension mechanism, the four-TTL age-limit restart, the 'not_found' outcome, and the fact that any tool call renews. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences each earn their place: first states the core behavior, second gives usage guidance, third covers return values. No fluff, and the most important information is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a one-parameter tool with an output schema and safety annotations, the description fully covers behavior, usage conditions, alternatives, return values, and error cases. Nothing an agent needs to invoke it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the single agent parameter is fully documented in the schema. The description does not add parameter-level detail, which is acceptable because the schema already carries that burden.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific action (extend leases by original TTL) and resource (all held leases), and explicitly contrasts with claim for taking new paths. It clearly differentiates renew from its siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives an explicit when-to-use condition ('Needed only during long work with no other call'), explains why (any tool call already renews), and names the alternative for different situations ('to take new paths use claim').

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

statusA
Read-only

Report the daemon's health: counts of claims, tasks, contracts, notices, decisions and notes, the swarm lead, the last persistence failure and the files skipped at load. verbose=true adds up to 50 active agents with what they hold. Use for a health check or to find the lead; it publishes nothing and takes no lease. For your own leases use claims_list, and for how to work with Tirith use guide.

ParametersJSON Schema
NameRequiredDescriptionDefault
agentNoYour stable agent name, optional here.
verboseNoAlso list active agents (at most 50) with what they hold.

Output Schema

ParametersJSON Schema
NameRequiredDescription
nowNoRFC 3339 daemon clock.
seqNoMutations applied since start.
leadNoThe agent holding .tirith/lead, or null.
agentsNoWith verbose, at most 50: agent, paths_count, expires_at, tasks_in_progress.
claimsNoLive claims.
memoryNoMemory notes.
statusYesok. invalid: a malformed agent name.
messageNoHuman-readable detail, on most outcomes other than ok.
noticesNoNotices.
versionNoThe daemon's version.
contractsNoContracts.
decisionsNoDecisions.
started_atNoRFC 3339.
tasks_doneNoTasks done.
tasks_openNoTasks not done.
load_errorsNoFiles or lines skipped at startup: path, line, error.
uptime_secsNoSeconds since start.
agents_activeNoAgents holding a claim or a task.
persist_errorNoThe last failure to write state to disk, or null.
tasks_orphanedNoTasks returned to todo because their owner went silent.
lead_expires_atNoWith verbose: RFC 3339 end of the lead's lease.
agents_truncatedNoWith verbose: more agents than were listed.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already carry readOnlyHint=true, and the description reinforces this with 'publishes nothing and takes no lease' – a more specific behavioral disclosure about side effects. It also surfaces the verbose behavior (lists up to 50 active agents) and the report's contents. While it doesn't discuss auth or rate limits, the core side-effect transparency goes beyond the annotation and is meaningful for an agent deciding whether to call this safely.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and front-loaded with the tool's core purpose, followed by usage guidance and alternatives. Every sentence earns its place: health report contents, verbose behavior, when to use, and explicit exclusions. There is no filler or repetition, making it easy for an agent to scan and act.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only health check with no required parameters, the description covers all necessary context: what the report contains, how verbose changes output, that it has no side effects, and how to choose alternatives. The presence of an output schema means return-value details need not be in the description. Nothing critical is missing for an agent to call this tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description does not add new meaning to the 'agent' parameter beyond the schema, and for 'verbose' it essentially restates the schema description ('verbose=true adds up to 50 active agents with what they hold'). It adds no format, default, or interaction detail not already present in the structured field descriptions, so no bonus is warranted.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Report the daemon's health', then enumerates the exact content of the report (counts, swarm lead, persistence failure, skipped files). It also distinguishes itself from siblings by explicitly stating it 'publishes nothing and takes no lease', which sets it apart from tools like claims_list or notice_publish. An agent can immediately know what this tool is for and what it is not.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit usage direction: 'Use for a health check or to find the lead'. It also provides clear exclusions and alternatives: 'it publishes nothing and takes no lease. For your own leases use claims_list, and for how to work with Tirith use guide.' This is exactly the kind of when-to-use/when-not-to-use guidance that lets an agent route correctly without opening sibling schemas.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

task_createA

Add a todo task to the shared board for any agent to pull. depends_on holds it back until those tasks are done, higher priority is pulled first, and paths lets task_pull keep agents off each other's files. Use to queue work, not to start it: task_pull assigns work and task_update changes a task. Returns the task with its id.

ParametersJSON Schema
NameRequiredDescriptionDefault
agentYesYour stable agent name.
pathsNoPaths the task will likely touch.
titleYesShort imperative title.
priorityNoHigher pulls first. Default 0.
depends_onNoTask ids that must be done first.
descriptionNoWhat needs doing, for whoever pulls the task.

Output Schema

ParametersJSON Schema
NameRequiredDescription
taskNoThe new task: id, title, description, priority, depends_on, paths, created_by, created_at, updated_at, notes, and state: its status with owner (in_progress), owner and reason (blocked), or by (done).
statusYesok. not_found: an unknown depends_on id. invalid: bad input or an ambiguous id prefix.
messageNoHuman-readable detail, on most outcomes other than ok.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the sparse annotation (destructiveHint=false) by disclosing key behaviors: depends_on blocks until dependencies complete, higher priority is pulled first, paths help task_pull avoid file collisions, and the tool returns the created task with its id. It also clarifies the tool only queues work and does not start it.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences, front-loaded with purpose, then key behavior, then routing guidance. Every sentence earns its place with no redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present and full parameter descriptions in the schema, the description is complete for an agent deciding whether and how to call it. It covers purpose, workflow semantics, alternative tools, and return value.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is already 100%, so the baseline is 3. The description adds meaning on top by explaining the workflow effect of depends_on, priority, and paths in relation to task_pull, which the schema descriptions only partially convey.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description opens with a specific verb and resource: 'Add a todo task to the shared board for any agent to pull.' It clearly differentiates from siblings by explicitly naming task_pull and task_update and stating what each sibling does.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states when to use this tool vs alternatives: 'Use to queue work, not to start it: task_pull assigns work and task_update changes a task.' This gives an agent direct routing guidance between sibling tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

task_listA
Read-only

List tasks on the board, filtered by status or owner, most recently updated first. Use to inspect the board without taking anything; to take work use task_pull. Rows are compact, 20 rows per page; pass next_before as before for older rows.

ParametersJSON Schema
NameRequiredDescriptionDefault
agentYesYour stable agent name.
limitNoRows to return (default 20, max 200), most recently updated first.
ownerNoOnly tasks owned by this agent.
beforeNoOnly tasks updated before this cursor: an RFC 3339 timestamp or a previous response's `next_before`.
statusNoOnly tasks with this status.

Output Schema

ParametersJSON Schema
NameRequiredDescription
countNoRows in this response.
tasksNoMost recently updated first; null fields and empty arrays are omitted, ids shortened to 8 characters.
totalNoRows that matched, across all pages.
statusYesok. invalid: bad input.
messageNoHuman-readable detail, on most outcomes other than ok.
truncatedNoTrue when older rows were left out.
next_beforeNoPresent when truncated: pass it back as before for the next older page.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, so the safety profile is covered. The description adds useful behavioral context beyond that: it is non-destructive ('without taking anything'), it returns compact rows, it paginates at 20 rows per page, and it orders by most recently updated. It also explains the cursor semantics ('pass next_before as before'). This adds meaningful behavioral detail without contradicting the annotation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, no filler. The core purpose and ordering are front-loaded, the usage distinction comes second, and the pagination detail is last. Every sentence earns its place and the whole description is compact.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only list tool with a 100%-covered schema and an output schema present, the description covers the essential behavioral aspects: what it lists, how it filters, how it orders, how pagination works, and when to use the sibling instead. Nothing an agent needs to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all five parameters. The description adds a little extra meaning by explaining the pagination cursor relationship ('pass next_before as before') and the default/max row counts, but it doesn't need to compensate for any schema gaps. Baseline 3 is appropriate when the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('List'), a resource ('tasks on the board'), and two filtering dimensions (status or owner), plus an ordering rule (most recently updated first). It also distinguishes itself from the sibling task_pull by explicitly saying it is for inspection, not taking work. This is a clear, specific purpose that an agent can act on without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly says when to use this tool ('inspect the board without taking anything') and names the alternative for taking work ('to take work use task_pull'). It also gives pagination guidance ('pass next_before as before for older rows'). This is explicit when/when-not guidance with a named alternative, which is exactly what the dimension asks for.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

task_pullA

Take the next task: the highest-priority todo whose dependencies are done becomes in_progress and yours, preferring tasks whose paths nobody else holds. Use to get work; to look without taking use task_list, and to change a named task use task_update. none means nothing is unblocked; a task that comes with waiting_on overlaps paths others hold, so coordinate before editing them. wait_secs waits server-side for work instead of you polling.

ParametersJSON Schema
NameRequiredDescriptionDefault
agentYesYour stable agent name.
wait_secsNoWait up to this many seconds (max 120) while todo tasks are claimed or wait on dependencies.

Output Schema

ParametersJSON Schema
NameRequiredDescription
taskNoThe task you now own: id, title, description, priority, depends_on, paths, created_by, created_at, updated_at, notes, and state: its status with owner (in_progress), owner and reason (blocked), or by (done).
statusYesok: the task is yours, in_progress. none: no todo task is unblocked. cancelled: a wait whose caller left. invalid: bad input.
messageNoHuman-readable detail, on most outcomes other than ok.
waiting_onNoPresent when the task's paths overlap what others hold: path, owner. Coordinate before editing those.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the sparse annotation (destructiveHint=false), the description discloses that the selected task 'becomes in_progress and yours', describes the path-preference selection strategy, clarifies that wait_secs 'waits server-side for work instead of you polling,' and explains the meaning of 'none' and 'waiting_on' for coordination. There is no contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Every sentence earns its place: the first delivers the core action and selection rule, the second routes to alternatives, and the third clarifies return semantics and the wait parameter. The most important information is front-loaded, and there is no filler or repetition of schema content.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's moderate complexity, an output schema exists, and the annotation is minimal, the description covers selection algorithm, side effect (ownership), usage alternatives, and edge-case interpretation ('none' and 'waiting_on'). It provides everything an agent needs to invoke the tool correctly and handle the result, making it complete for its context.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3 with both parameters already documented. The description adds extra behavioral nuance for wait_secs ('waits server-side for work instead of you polling') that is not in the schema, lifting it above baseline. The agent parameter is not further elaborated, but the schema's 'Your stable agent name' is sufficient.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with 'Take the next task' – a specific verb and resource – then precisely defines the selection criteria (highest-priority todo with dependencies done, becoming in_progress and yours). It also explicitly differentiates from task_list and task_update, so an agent can distinguish the tool from key siblings without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description states exactly when to use this tool ('Use to get work') and when not to, naming alternatives: 'to look without taking use task_list, and to change a named task use task_update.' It also provides post-return guidance about interpreting 'none' and coordinating on 'waiting_on' tasks, covering when-to-use and exclusion criteria explicitly.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

task_updateA
Idempotent

Change one task's status: done to finish it, todo to hand it back, blocked to park it with note as the reason, in_progress to take it by id. Changing a task another agent has in_progress is a conflict naming the owner, unless force, which is recorded in the task's notes. To get the next task without naming one use task_pull. Returns the task in full.

ParametersJSON Schema
NameRequiredDescriptionDefault
noteNoA note to append. For `blocked`, this is the reason.
agentYesYour stable agent name.
forceNoTake or close a task another agent has in progress.
statusYesOne of `todo`, `in_progress`, `blocked`, `done`.
task_idYesThe task's id, or a unique prefix of it.

Output Schema

ParametersJSON Schema
NameRequiredDescription
taskNoThe task after the change: id, title, description, priority, depends_on, paths, created_by, created_at, updated_at, notes, and state: its status with owner (in_progress), owner and reason (blocked), or by (done).
ownerNoOn conflict: the agent that has the task in_progress.
sinceNoOn conflict: RFC 3339 time that agent took it.
statusYesok. conflict: another agent has it in_progress and force was not set. not_found: no such task. invalid: bad status or an ambiguous id prefix.
messageNoHuman-readable detail, on most outcomes other than ok.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the idempotentHint and destructiveHint annotations, the description discloses conflict behavior when another agent has the task in_progress, the meaning and effect of force, and that the action is recorded in the task's notes. It also states the return value is the full task, adding useful behavioral context not present in annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three dense sentences deliver the essential information in order: status semantics, conflict/force rules, alternative routing, and return value. There is no filler or repetition of schema details.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the output schema exists and annotations cover safety, the description sufficiently covers all status transitions, conflict handling, force behavior, note usage, return shape, and the main sibling alternative. Nothing important is missing for an agent to invoke the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds real semantic value by explaining what each status means in context: done finishes, todo hands back, blocked parks with a note as reason, and in_progress takes by id. It also clarifies the force/note interaction beyond the raw parameter descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Change one task's status,' then maps each allowed status to its intended effect. It also distinguishes itself from task_pull by pointing users to that sibling for getting the next task without naming one.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It clearly states when to use the tool and gives an explicit alternative: 'To get the next task without naming one use task_pull.' It also explains the conflict scenario and force flag. It doesn't enumerate all sibling exclusions like task_create or task_list, but the primary routing guidance is solid.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 23 tool updatesv1.1.2
    • Changedclaim7 fields changed
      • addedInput schema / properties / agent / description
        Added value: +"Your stable agent name."
      • addedInput schema / properties / brief / description
        Added value: +"Attach the brief. Default true."
      • addedInput schema / properties / paths / description
        Added value: +"Repo-relative files or directories. A directory covers everything beneath it."
      • addedInput schema / properties / reason / description
        Added value: +"Why you need these paths; shown to any agent that is refused."
      • addedInput schema / properties / ttl_secs / description
        Added value: +"Lease length in seconds. Default 600, max 3600."
      • addedInput schema / properties / wait_secs / description
        Added value: +"On conflict, wait up to this many seconds (max 120) for the paths to free."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "description": "Any result may also carry lost, inbox, inbox_more and persist_error; see guide.",
        +  "properties": {
        +    "absorbed_paths": {
        +      "description": "Paths you held beneath a directory just claimed, folded into it.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "claim_id": {
        +      "description": "The new lease; null when every path was only renewed.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "conflicts": {
        +      "description": "On conflict, one per overlapping path: path, overlaps, owner, reason, expires_at.",
        +      "items": {
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "contracts": {
        +      "description": "Brief: up to 5 contracts these paths consume (name, version, kind). Bodies via contract_get.",
        +      "items": {
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "decisions": {
        +      "description": "Brief: up to 5 decisions affecting these paths (id, title).",
        +      "items": {
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "expires_at": {
        +      "description": "RFC 3339 end of the lease unless renewed.",
        +      "type": "string"
        +    },
        +    "memory": {
        +      "description": "Brief: up to 5 memory notes about these paths, as digests with an excerpt. Bodies via memory_read.",
        +      "items": {
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "message": {
        +      "description": "Human-readable detail, on most outcomes other than ok.",
        +      "type": "string"
        +    },
        +    "more": {
        +      "description": "Per brief section, how many matching rows were left out; page with the list tools when not zero.",
        +      "type": "object"
        +    },
        +    "new_paths": {
        +      "description": "Paths claimed by this call.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "notices": {
        +      "description": "Brief: up to 5 unread notices for these paths (id, kind, summary, by). Now marked seen by you.",
        +      "items": {
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "previous_owner": {
        +      "description": "For a new path whose lease another agent lost in the last hour: path, owner, reaped_at. It may be half-edited.",
        +      "items": {
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "renewed_paths": {
        +      "description": "Paths you already held, renewed.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "status": {
        +      "description": "ok: every path is yours. conflict: nothing was claimed. cancelled: a wait whose caller left. invalid: bad input.",
        +      "enum": [
        +        "ok",
        +        "conflict",
        +        "not_found",
        +        "none",
        +        "invalid",
        +        "cancelled"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "status"
        +  ],
        +  "type": "object"
        +}
    • Changedclaims_list6 fields changed
      • addedInput schema / properties / agent / description
        Added value: +"Your stable agent name."
      • addedInput schema / properties / all / description
        Added value: +"List every live claim, not just yours and those overlapping `path`."
      • addedInput schema / properties / before / description
        Added value: +"Only claims older than this cursor: an RFC 3339 timestamp or a\nprevious response's `next_before`."
      • addedInput schema / properties / limit / description
        Added value: +"Rows to return (default 20, max 200), newest first."
      • addedInput schema / properties / path / description
        Added value: +"Also include claims overlapping this path, whoever holds them."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "description": "Any result may also carry lost, inbox, inbox_more and persist_error; see guide.",
        +  "properties": {
        +    "claims": {
        +      "description": "id, owner, paths, reason, claimed_at, expires_at, ttl_secs. Expired claims are never listed.",
        +      "items": {
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "count": {
        +      "description": "Rows in this response.",
        +      "type": "integer"
        +    },
        +    "message": {
        +      "description": "Human-readable detail, on most outcomes other than ok.",
        +      "type": "string"
        +    },
        +    "next_before": {
        +      "description": "Present when truncated: pass it back as before for the next older page.",
        +      "type": "string"
        +    },
        +    "status": {
        +      "description": "ok. invalid: bad input.",
        +      "enum": [
        +        "ok",
        +        "conflict",
        +        "not_found",
        +        "none",
        +        "invalid",
        +        "cancelled"
        +      ],
        +      "type": "string"
        +    },
        +    "total": {
        +      "description": "Rows that matched, across all pages.",
        +      "type": "integer"
        +    },
        +    "truncated": {
        +      "description": "True when older rows were left out.",
        +      "type": "boolean"
        +    }
        +  },
        +  "required": [
        +    "status"
        +  ],
        +  "type": "object"
        +}
    • Changedcontract_get3 fields changed
      • addedInput schema / properties / agent / description
        Added value: +"Your stable agent name."
      • addedInput schema / properties / name / description
        Added value: +"The contract's name, its id, or a unique prefix of the id."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "description": "Any result may also carry lost, inbox, inbox_more and persist_error; see guide.",
        +  "properties": {
        +    "contract": {
        +      "description": "In full: id, name, kind, consumers, current (version, shape, notes, published_by, published_at), and history, oldest first.",
        +      "type": "object"
        +    },
        +    "message": {
        +      "description": "Human-readable detail, on most outcomes other than ok.",
        +      "type": "string"
        +    },
        +    "status": {
        +      "description": "ok. not_found: no such contract. invalid: an ambiguous id prefix.",
        +      "enum": [
        +        "ok",
        +        "conflict",
        +        "not_found",
        +        "none",
        +        "invalid",
        +        "cancelled"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "status"
        +  ],
        +  "type": "object"
        +}
    • Changedcontract_list7 fields changed
      • addedInput schema / properties / agent / description
        Added value: +"Your stable agent name."
      • addedInput schema / properties / before / description
        Added value: +"Only contracts published before this cursor: an RFC 3339 timestamp\nor a previous response's `next_before`."
      • addedInput schema / properties / kind / description
        Added value: +"Only contracts of this kind."
      • addedInput schema / properties / kind / enum
        Added value: +[
        +  "http",
        +  "function",
        +  "type",
        +  "event",
        +  "cli",
        +  "other"
        +]
      • addedInput schema / properties / limit / description
        Added value: +"Rows to return (default 20, max 200), most recently published first."
      • addedInput schema / properties / path / description
        Added value: +"Only contracts whose consumers overlap this path."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "description": "Any result may also carry lost, inbox, inbox_more and persist_error; see guide.",
        +  "properties": {
        +    "contracts": {
        +      "description": "Most recently published first, compact: id, name, kind, consumers, current version. Shapes via contract_get.",
        +      "items": {
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "count": {
        +      "description": "Rows in this response.",
        +      "type": "integer"
        +    },
        +    "message": {
        +      "description": "Human-readable detail, on most outcomes other than ok.",
        +      "type": "string"
        +    },
        +    "next_before": {
        +      "description": "Present when truncated: pass it back as before for the next older page.",
        +      "type": "string"
        +    },
        +    "status": {
        +      "description": "ok. invalid: bad input.",
        +      "enum": [
        +        "ok",
        +        "conflict",
        +        "not_found",
        +        "none",
        +        "invalid",
        +        "cancelled"
        +      ],
        +      "type": "string"
        +    },
        +    "total": {
        +      "description": "Rows that matched, across all pages.",
        +      "type": "integer"
        +    },
        +    "truncated": {
        +      "description": "True when older rows were left out.",
        +      "type": "boolean"
        +    }
        +  },
        +  "required": [
        +    "status"
        +  ],
        +  "type": "object"
        +}
    • Changedcontract_publish9 fields changed
      • addedInput schema / properties / agent / description
        Added value: +"Your stable agent name."
      • addedInput schema / properties / consumers / description
        Added value: +"Paths expected to depend on this contract."
      • addedInput schema / properties / expected_version / description
        Added value: +"Refuse unless the contract is at this version now (0 = absent)."
      • addedInput schema / properties / kind / description
        Added value: +"One of `http`, `function`, `type`, `event`, `cli`, `other`."
      • addedInput schema / properties / kind / enum
        Added value: +[
        +  "http",
        +  "function",
        +  "type",
        +  "event",
        +  "cli",
        +  "other"
        +]
      • addedInput schema / properties / name / description
        Added value: +"Unique contract name, for example `POST /api/sessions` or `State::claim`."
      • addedInput schema / properties / notes / description
        Added value: +"Free-text notes stored with this version."
      • addedInput schema / properties / shape / description
        Added value: +"The interface shape as JSON: signatures, request and response types, errors."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "description": "Any result may also carry lost, inbox, inbox_more and persist_error; see guide.",
        +  "properties": {
        +    "contract": {
        +      "description": "id, name, kind, consumers, current (version, shape, notes, published_by, published_at), history.",
        +      "type": "object"
        +    },
        +    "current_version": {
        +      "description": "On conflict: the version the contract is at.",
        +      "type": "integer"
        +    },
        +    "message": {
        +      "description": "Human-readable detail, on most outcomes other than ok.",
        +      "type": "string"
        +    },
        +    "notice_id": {
        +      "description": "The change notice emitted to consumers of a republished contract."
        +    },
        +    "previous_version": {
        +      "description": "The version this one replaced; absent or null on a first publish."
        +    },
        +    "published_by": {
        +      "description": "On conflict: who published that version."
        +    },
        +    "status": {
        +      "description": "ok. conflict: expected_version was set and the contract is at another version. invalid: bad input.",
        +      "enum": [
        +        "ok",
        +        "conflict",
        +        "not_found",
        +        "none",
        +        "invalid",
        +        "cancelled"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "status"
        +  ],
        +  "type": "object"
        +}
    • Changeddecision_list6 fields changed
      • addedInput schema / properties / agent / description
        Added value: +"Your stable agent name."
      • addedInput schema / properties / before / description
        Added value: +"Only decisions recorded before this cursor: an RFC 3339 timestamp\nor a previous response's `next_before`."
      • addedInput schema / properties / limit / description
        Added value: +"Rows to return (default 20, max 200), newest first."
      • addedInput schema / properties / path / description
        Added value: +"Only decisions affecting this path."
      • addedInput schema / properties / query / description
        Added value: +"Case-insensitive text to search for."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "description": "Any result may also carry lost, inbox, inbox_more and persist_error; see guide.",
        +  "properties": {
        +    "count": {
        +      "description": "Rows in this response.",
        +      "type": "integer"
        +    },
        +    "decisions": {
        +      "description": "Newest first: id, title, decision, rationale, alternatives, affects_paths, recorded_by, recorded_at.",
        +      "items": {
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "message": {
        +      "description": "Human-readable detail, on most outcomes other than ok.",
        +      "type": "string"
        +    },
        +    "next_before": {
        +      "description": "Present when truncated: pass it back as before for the next older page.",
        +      "type": "string"
        +    },
        +    "status": {
        +      "description": "ok. invalid: bad input.",
        +      "enum": [
        +        "ok",
        +        "conflict",
        +        "not_found",
        +        "none",
        +        "invalid",
        +        "cancelled"
        +      ],
        +      "type": "string"
        +    },
        +    "total": {
        +      "description": "Rows that matched, across all pages.",
        +      "type": "integer"
        +    },
        +    "truncated": {
        +      "description": "True when older rows were left out.",
        +      "type": "boolean"
        +    }
        +  },
        +  "required": [
        +    "status"
        +  ],
        +  "type": "object"
        +}
    • Changeddecision_record7 fields changed
      • addedInput schema / properties / affects_paths / description
        Added value: +"Paths the decision constrains."
      • addedInput schema / properties / agent / description
        Added value: +"Your stable agent name."
      • addedInput schema / properties / alternatives / description
        Added value: +"The alternatives that were considered and rejected."
      • addedInput schema / properties / decision / description
        Added value: +"What was decided, stated so it can be followed."
      • addedInput schema / properties / rationale / description
        Added value: +"Why it was decided."
      • addedInput schema / properties / title / description
        Added value: +"Short title, the line shown in briefs."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "description": "Any result may also carry lost, inbox, inbox_more and persist_error; see guide.",
        +  "properties": {
        +    "decision": {
        +      "description": "id, title, decision, rationale, alternatives, affects_paths, recorded_by, recorded_at, and the permalink of its committed file.",
        +      "type": "object"
        +    },
        +    "message": {
        +      "description": "Human-readable detail, on most outcomes other than ok.",
        +      "type": "string"
        +    },
        +    "status": {
        +      "description": "ok. invalid: bad input.",
        +      "enum": [
        +        "ok",
        +        "conflict",
        +        "not_found",
        +        "none",
        +        "invalid",
        +        "cancelled"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "status"
        +  ],
        +  "type": "object"
        +}
    • Addedguide
    • Changedmemory_delete3 fields changed
      • addedInput schema / properties / agent / description
        Added value: +"Your stable agent name."
      • addedInput schema / properties / name / description
        Added value: +"A permalink, an id, or an exact title."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "description": "Any result may also carry lost, inbox, inbox_more and persist_error; see guide.",
        +  "properties": {
        +    "message": {
        +      "description": "Human-readable detail, on most outcomes other than ok.",
        +      "type": "string"
        +    },
        +    "removed": {
        +      "description": "A digest of the deleted note: permalink, title, kind, paths, tags, updated_at, and a 160-character excerpt.",
        +      "type": "object"
        +    },
        +    "status": {
        +      "description": "ok. not_found: no such note.",
        +      "enum": [
        +        "ok",
        +        "conflict",
        +        "not_found",
        +        "none",
        +        "invalid",
        +        "cancelled"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "status"
        +  ],
        +  "type": "object"
        +}
    • Changedmemory_read4 fields changed
      • addedInput schema / properties / agent / description
        Added value: +"Your stable agent name."
      • addedInput schema / properties / depth / description
        Added value: +"How many relation hops of related notes to include, 0 to 3."
      • addedInput schema / properties / name / description
        Added value: +"A permalink, an id, or an exact title."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "description": "Any result may also carry lost, inbox, inbox_more and persist_error; see guide.",
        +  "properties": {
        +    "message": {
        +      "description": "Human-readable detail, on most outcomes other than ok.",
        +      "type": "string"
        +    },
        +    "note": {
        +      "description": "The whole note, body included: id, permalink, title, kind, body, observations, relations, paths, tags, author, updated_by, created_at, updated_at.",
        +      "type": "object"
        +    },
        +    "related": {
        +      "description": "With depth above 0, at most 20 linked notes as digests: permalink, title, kind, paths, tags, updated_at, and a 160-character excerpt.",
        +      "items": {
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "status": {
        +      "description": "ok. not_found: no such note. invalid: depth above 3.",
        +      "enum": [
        +        "ok",
        +        "conflict",
        +        "not_found",
        +        "none",
        +        "invalid",
        +        "cancelled"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "status"
        +  ],
        +  "type": "object"
        +}
    • Changedmemory_search9 fields changed
      • addedInput schema / properties / agent / description
        Added value: +"Your stable agent name."
      • addedInput schema / properties / kind / description
        Added value: +"Only notes of this kind."
      • addedInput schema / properties / kind / enum
        Added value: +[
        +  "fact",
        +  "lesson",
        +  "gotcha",
        +  "handoff",
        +  "research",
        +  "decision",
        +  "note"
        +]
      • addedInput schema / properties / limit / description
        Added value: +"How many to return. Default 10, max 50."
      • addedInput schema / properties / path / description
        Added value: +"Only notes whose paths overlap this one."
      • addedInput schema / properties / query / description
        Added value: +"Free text. Omit for recent activity."
      • addedInput schema / properties / since / description
        Added value: +"Only notes updated at or after this RFC 3339 timestamp."
      • addedInput schema / properties / tag / description
        Added value: +"Only notes carrying this tag."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "description": "Any result may also carry lost, inbox, inbox_more and persist_error; see guide.",
        +  "properties": {
        +    "count": {
        +      "description": "Rows in this response.",
        +      "type": "integer"
        +    },
        +    "message": {
        +      "description": "Human-readable detail, on most outcomes other than ok.",
        +      "type": "string"
        +    },
        +    "notes": {
        +      "description": "Best match first, or newest first with no query. Digests, never bodies: permalink, title, kind, paths, tags, updated_at, and a 160-character excerpt, and score.",
        +      "items": {
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "status": {
        +      "description": "ok. invalid: bad kind, since, or input.",
        +      "enum": [
        +        "ok",
        +        "conflict",
        +        "not_found",
        +        "none",
        +        "invalid",
        +        "cancelled"
        +      ],
        +      "type": "string"
        +    },
        +    "truncated": {
        +      "description": "True when limit hid further matches.",
        +      "type": "boolean"
        +    }
        +  },
        +  "required": [
        +    "status"
        +  ],
        +  "type": "object"
        +}
    • Changedmemory_write10 fields changed
      • addedInput schema / properties / agent / description
        Added value: +"Your stable agent name."
      • addedInput schema / properties / body / description
        Added value: +"The note itself, as Markdown."
      • addedInput schema / properties / if_updated_at / description
        Added value: +"RFC 3339 `updated_at` from a read; refused if the note changed since."
      • addedInput schema / properties / kind / description
        Added value: +"One of `fact`, `lesson`, `gotcha`, `handoff`, `research`, `decision`,\n`note` (the default)."
      • addedInput schema / properties / kind / enum
        Added value: +[
        +  "fact",
        +  "lesson",
        +  "gotcha",
        +  "handoff",
        +  "research",
        +  "decision",
        +  "note"
        +]
      • addedInput schema / properties / paths / description
        Added value: +"Repo-relative paths this note is about."
      • addedInput schema / properties / permalink / description
        Added value: +"Overwrite this note instead of matching on the title."
      • addedInput schema / properties / tags / description
        Added value: +"Tags for filtering; lowercased, and a leading `#` is dropped."
      • addedInput schema / properties / title / description
        Added value: +"Short title. Becomes the permalink the first time."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "description": "Any result may also carry lost, inbox, inbox_more and persist_error; see guide.",
        +  "properties": {
        +    "created": {
        +      "description": "True for a new note, false when an existing title or permalink was updated.",
        +      "type": "boolean"
        +    },
        +    "message": {
        +      "description": "Human-readable detail, on most outcomes other than ok.",
        +      "type": "string"
        +    },
        +    "note": {
        +      "description": "The note as stored: id, permalink, title, kind, body, observations, relations, paths, tags, author, updated_by, created_at, updated_at.",
        +      "type": "object"
        +    },
        +    "permalink": {
        +      "description": "On conflict: the note that changed."
        +    },
        +    "status": {
        +      "description": "ok. conflict: if_updated_at was set and the note changed since. not_found: an explicit permalink that does not exist. invalid: bad kind or input.",
        +      "enum": [
        +        "ok",
        +        "conflict",
        +        "not_found",
        +        "none",
        +        "invalid",
        +        "cancelled"
        +      ],
        +      "type": "string"
        +    },
        +    "updated_at": {
        +      "description": "On conflict: its real updated_at; read again and retry."
        +    }
        +  },
        +  "required": [
        +    "status"
        +  ],
        +  "type": "object"
        +}
    • Changedmessage_list7 fields changed
      • addedInput schema / properties / agent / description
        Added value: +"Your stable agent name."
      • addedInput schema / properties / before / description
        Added value: +"Only messages older than this cursor: an RFC 3339 timestamp or a\nprevious response's `next_before`."
      • addedInput schema / properties / limit / description
        Added value: +"Rows to return; default 20, max 200."
      • addedInput schema / properties / since / description
        Added value: +"Only messages sent at or after this RFC 3339 instant."
      • addedInput schema / properties / unread / description
        Added value: +"Only messages to you that you have not received yet."
      • addedInput schema / properties / with / description
        Added value: +"Only the conversation with this agent."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "description": "Any result may also carry lost, inbox, inbox_more and persist_error; see guide.",
        +  "properties": {
        +    "count": {
        +      "description": "Rows in this response.",
        +      "type": "integer"
        +    },
        +    "message": {
        +      "description": "Human-readable detail, on most outcomes other than ok.",
        +      "type": "string"
        +    },
        +    "messages": {
        +      "description": "Newest first, sent or received by you: id, from, to, text, reply_to, paths, at.",
        +      "items": {
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "next_before": {
        +      "description": "Present when truncated: pass it back as before for the next older page.",
        +      "type": "string"
        +    },
        +    "status": {
        +      "description": "ok. invalid: bad input.",
        +      "enum": [
        +        "ok",
        +        "conflict",
        +        "not_found",
        +        "none",
        +        "invalid",
        +        "cancelled"
        +      ],
        +      "type": "string"
        +    },
        +    "total": {
        +      "description": "Rows that matched, across all pages.",
        +      "type": "integer"
        +    },
        +    "truncated": {
        +      "description": "True when older rows were left out.",
        +      "type": "boolean"
        +    }
        +  },
        +  "required": [
        +    "status"
        +  ],
        +  "type": "object"
        +}
    • Changedmessage_send6 fields changed
      • addedInput schema / properties / agent / description
        Added value: +"Your stable agent name."
      • addedInput schema / properties / paths / description
        Added value: +"Paths the message is about."
      • addedInput schema / properties / reply_to / description
        Added value: +"Id, or a unique prefix, of the message this one answers."
      • addedInput schema / properties / text / description
        Added value: +"The message, at most 1000 characters."
      • addedInput schema / properties / to / description
        Added value: +"The recipient's agent name, `*` for every agent active in the last\nhour, or `human` for the human queue."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "description": "Any result may also carry lost, inbox, inbox_more and persist_error; see guide.",
        +  "properties": {
        +    "message": {
        +      "description": "On ok, the message as sent: id, from, to, text, reply_to, paths, at; audience lists the recipients of a broadcast. On any other outcome, why, as text.",
        +      "type": [
        +        "object",
        +        "string"
        +      ]
        +    },
        +    "status": {
        +      "description": "ok. not_found: an unknown reply_to. invalid: empty or over-long text, a bad recipient, or agent human.",
        +      "enum": [
        +        "ok",
        +        "conflict",
        +        "not_found",
        +        "none",
        +        "invalid",
        +        "cancelled"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "status"
        +  ],
        +  "type": "object"
        +}
    • Changednotice_list8 fields changed
      • addedInput schema / properties / agent / description
        Added value: +"Your stable agent name."
      • addedInput schema / properties / all / description
        Added value: +"With `unread`, look beyond the paths you hold."
      • addedInput schema / properties / before / description
        Added value: +"Only notices published before this cursor: an RFC 3339 timestamp\nor a previous response's `next_before`."
      • addedInput schema / properties / limit / description
        Added value: +"Rows to return (default 20, max 200), newest first."
      • addedInput schema / properties / path / description
        Added value: +"Only notices affecting this path."
      • addedInput schema / properties / since / description
        Added value: +"Only notices published at or after this RFC 3339 timestamp."
      • addedInput schema / properties / unread / description
        Added value: +"Only notices you neither published nor were already shown. Without\n`path` or `all`, this is scoped to the paths you currently hold."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "description": "Any result may also carry lost, inbox, inbox_more and persist_error; see guide.",
        +  "properties": {
        +    "count": {
        +      "description": "Rows in this response.",
        +      "type": "integer"
        +    },
        +    "message": {
        +      "description": "Human-readable detail, on most outcomes other than ok.",
        +      "type": "string"
        +    },
        +    "next_before": {
        +      "description": "Present when truncated: pass it back as before for the next older page.",
        +      "type": "string"
        +    },
        +    "notices": {
        +      "description": "Newest first: id, kind, summary, from, to, affected_paths, published_by, published_at. Rows returned for unread=true are now marked seen by you.",
        +      "items": {
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "status": {
        +      "description": "ok, with zero rows and a message when unread is scoped to paths and you hold none. invalid: bad input.",
        +      "enum": [
        +        "ok",
        +        "conflict",
        +        "not_found",
        +        "none",
        +        "invalid",
        +        "cancelled"
        +      ],
        +      "type": "string"
        +    },
        +    "total": {
        +      "description": "Rows that matched, across all pages.",
        +      "type": "integer"
        +    },
        +    "truncated": {
        +      "description": "True when older rows were left out.",
        +      "type": "boolean"
        +    }
        +  },
        +  "required": [
        +    "status"
        +  ],
        +  "type": "object"
        +}
    • Changednotice_publish9 fields changed
      • addedInput schema / properties / affected_paths / description
        Added value: +"Paths whose code must react."
      • addedInput schema / properties / agent / description
        Added value: +"Your stable agent name."
      • addedInput schema / properties / contract_id / description
        Added value: +"Related contract id, if any."
      • addedInput schema / properties / from / description
        Added value: +"The old name, location, or shape."
      • addedInput schema / properties / kind / description
        Added value: +"One of `rename`, `signature`, `removed`, `moved`, `behavior`."
      • addedInput schema / properties / kind / enum
        Added value: +[
        +  "rename",
        +  "signature",
        +  "removed",
        +  "moved",
        +  "behavior"
        +]
      • addedInput schema / properties / summary / description
        Added value: +"One-line summary, for example `renamed session_id to token`."
      • addedInput schema / properties / to / description
        Added value: +"The new name, location, or shape."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "description": "Any result may also carry lost, inbox, inbox_more and persist_error; see guide.",
        +  "properties": {
        +    "message": {
        +      "description": "Human-readable detail, on most outcomes other than ok.",
        +      "type": "string"
        +    },
        +    "notice": {
        +      "description": "id, kind, summary, from, to, affected_paths, contract_id, published_by, published_at.",
        +      "type": "object"
        +    },
        +    "status": {
        +      "description": "ok. not_found: an unknown contract_id. invalid: bad kind or input.",
        +      "enum": [
        +        "ok",
        +        "conflict",
        +        "not_found",
        +        "none",
        +        "invalid",
        +        "cancelled"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "status"
        +  ],
        +  "type": "object"
        +}
    • Changedrelease3 fields changed
      • addedInput schema / properties / agent / description
        Added value: +"Your stable agent name."
      • addedInput schema / properties / paths / description
        Added value: +"Paths to release. Omit to release everything you hold."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "description": "Any result may also carry lost, inbox, inbox_more and persist_error; see guide.",
        +  "properties": {
        +    "agent": {
        +      "description": "The caller.",
        +      "type": "string"
        +    },
        +    "message": {
        +      "description": "Human-readable detail, on most outcomes other than ok.",
        +      "type": "string"
        +    },
        +    "released": {
        +      "description": "The paths released.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "status": {
        +      "description": "ok, or not_found when you do not hold a named path (nothing is released). invalid: bad input.",
        +      "enum": [
        +        "ok",
        +        "conflict",
        +        "not_found",
        +        "none",
        +        "invalid",
        +        "cancelled"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "status"
        +  ],
        +  "type": "object"
        +}
    • Changedrenew2 fields changed
      • addedInput schema / properties / agent / description
        Added value: +"Your stable agent name."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "description": "Any result may also carry lost, inbox, inbox_more and persist_error; see guide.",
        +  "properties": {
        +    "agent": {
        +      "description": "The caller.",
        +      "type": "string"
        +    },
        +    "count": {
        +      "description": "Leases renewed.",
        +      "type": "integer"
        +    },
        +    "expires_at": {
        +      "description": "RFC 3339 latest expiry among the renewed leases.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "message": {
        +      "description": "Human-readable detail, on most outcomes other than ok.",
        +      "type": "string"
        +    },
        +    "status": {
        +      "description": "ok. not_found: you hold no claims. invalid: bad input.",
        +      "enum": [
        +        "ok",
        +        "conflict",
        +        "not_found",
        +        "none",
        +        "invalid",
        +        "cancelled"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "status"
        +  ],
        +  "type": "object"
        +}
    • Changedstatus3 fields changed
      • addedInput schema / properties / agent / description
        Added value: +"Your stable agent name, optional here."
      • addedInput schema / properties / verbose / description
        Added value: +"Also list active agents (at most 50) with what they hold."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "description": "Any result may also carry lost, inbox, inbox_more and persist_error; see guide.",
        +  "properties": {
        +    "agents": {
        +      "description": "With verbose, at most 50: agent, paths_count, expires_at, tasks_in_progress.",
        +      "items": {
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "agents_active": {
        +      "description": "Agents holding a claim or a task.",
        +      "type": "integer"
        +    },
        +    "agents_truncated": {
        +      "description": "With verbose: more agents than were listed.",
        +      "type": "boolean"
        +    },
        +    "claims": {
        +      "description": "Live claims.",
        +      "type": "integer"
        +    },
        +    "contracts": {
        +      "description": "Contracts.",
        +      "type": "integer"
        +    },
        +    "decisions": {
        +      "description": "Decisions.",
        +      "type": "integer"
        +    },
        +    "lead": {
        +      "description": "The agent holding .tirith/lead, or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "lead_expires_at": {
        +      "description": "With verbose: RFC 3339 end of the lead's lease."
        +    },
        +    "load_errors": {
        +      "description": "Files or lines skipped at startup: path, line, error.",
        +      "items": {
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "memory": {
        +      "description": "Memory notes.",
        +      "type": "integer"
        +    },
        +    "message": {
        +      "description": "Human-readable detail, on most outcomes other than ok.",
        +      "type": "string"
        +    },
        +    "notices": {
        +      "description": "Notices.",
        +      "type": "integer"
        +    },
        +    "now": {
        +      "description": "RFC 3339 daemon clock.",
        +      "type": "string"
        +    },
        +    "persist_error": {
        +      "description": "The last failure to write state to disk, or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "seq": {
        +      "description": "Mutations applied since start.",
        +      "type": "integer"
        +    },
        +    "started_at": {
        +      "description": "RFC 3339.",
        +      "type": "string"
        +    },
        +    "status": {
        +      "description": "ok. invalid: a malformed agent name.",
        +      "enum": [
        +        "ok",
        +        "conflict",
        +        "not_found",
        +        "none",
        +        "invalid",
        +        "cancelled"
        +      ],
        +      "type": "string"
        +    },
        +    "tasks_done": {
        +      "description": "Tasks done.",
        +      "type": "integer"
        +    },
        +    "tasks_open": {
        +      "description": "Tasks not done.",
        +      "type": "integer"
        +    },
        +    "tasks_orphaned": {
        +      "description": "Tasks returned to todo because their owner went silent.",
        +      "type": "integer"
        +    },
        +    "uptime_secs": {
        +      "description": "Seconds since start.",
        +      "type": "integer"
        +    },
        +    "version": {
        +      "description": "The daemon's version.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "status"
        +  ],
        +  "type": "object"
        +}
    • Changedtask_create7 fields changed
      • addedInput schema / properties / agent / description
        Added value: +"Your stable agent name."
      • addedInput schema / properties / depends_on / description
        Added value: +"Task ids that must be done first."
      • addedInput schema / properties / description / description
        Added value: +"What needs doing, for whoever pulls the task."
      • addedInput schema / properties / paths / description
        Added value: +"Paths the task will likely touch."
      • addedInput schema / properties / priority / description
        Added value: +"Higher pulls first. Default 0."
      • addedInput schema / properties / title / description
        Added value: +"Short imperative title."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "description": "Any result may also carry lost, inbox, inbox_more and persist_error; see guide.",
        +  "properties": {
        +    "message": {
        +      "description": "Human-readable detail, on most outcomes other than ok.",
        +      "type": "string"
        +    },
        +    "status": {
        +      "description": "ok. not_found: an unknown depends_on id. invalid: bad input or an ambiguous id prefix.",
        +      "enum": [
        +        "ok",
        +        "conflict",
        +        "not_found",
        +        "none",
        +        "invalid",
        +        "cancelled"
        +      ],
        +      "type": "string"
        +    },
        +    "task": {
        +      "description": "The new task: id, title, description, priority, depends_on, paths, created_by, created_at, updated_at, notes, and state: its status with owner (in_progress), owner and reason (blocked), or by (done).",
        +      "type": "object"
        +    }
        +  },
        +  "required": [
        +    "status"
        +  ],
        +  "type": "object"
        +}
    • Changedtask_list7 fields changed
      • addedInput schema / properties / agent / description
        Added value: +"Your stable agent name."
      • addedInput schema / properties / before / description
        Added value: +"Only tasks updated before this cursor: an RFC 3339 timestamp or a\nprevious response's `next_before`."
      • addedInput schema / properties / limit / description
        Added value: +"Rows to return (default 20, max 200), most recently updated first."
      • addedInput schema / properties / owner / description
        Added value: +"Only tasks owned by this agent."
      • addedInput schema / properties / status / description
        Added value: +"Only tasks with this status."
      • addedInput schema / properties / status / enum
        Added value: +[
        +  "todo",
        +  "in_progress",
        +  "blocked",
        +  "done"
        +]
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "description": "Any result may also carry lost, inbox, inbox_more and persist_error; see guide.",
        +  "properties": {
        +    "count": {
        +      "description": "Rows in this response.",
        +      "type": "integer"
        +    },
        +    "message": {
        +      "description": "Human-readable detail, on most outcomes other than ok.",
        +      "type": "string"
        +    },
        +    "next_before": {
        +      "description": "Present when truncated: pass it back as before for the next older page.",
        +      "type": "string"
        +    },
        +    "status": {
        +      "description": "ok. invalid: bad input.",
        +      "enum": [
        +        "ok",
        +        "conflict",
        +        "not_found",
        +        "none",
        +        "invalid",
        +        "cancelled"
        +      ],
        +      "type": "string"
        +    },
        +    "tasks": {
        +      "description": "Most recently updated first; null fields and empty arrays are omitted, ids shortened to 8 characters.",
        +      "items": {
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "total": {
        +      "description": "Rows that matched, across all pages.",
        +      "type": "integer"
        +    },
        +    "truncated": {
        +      "description": "True when older rows were left out.",
        +      "type": "boolean"
        +    }
        +  },
        +  "required": [
        +    "status"
        +  ],
        +  "type": "object"
        +}
    • Changedtask_pull3 fields changed
      • addedInput schema / properties / agent / description
        Added value: +"Your stable agent name."
      • addedInput schema / properties / wait_secs / description
        Added value: +"Wait up to this many seconds (max 120) while todo tasks are claimed or wait on dependencies."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "description": "Any result may also carry lost, inbox, inbox_more and persist_error; see guide.",
        +  "properties": {
        +    "message": {
        +      "description": "Human-readable detail, on most outcomes other than ok.",
        +      "type": "string"
        +    },
        +    "status": {
        +      "description": "ok: the task is yours, in_progress. none: no todo task is unblocked. cancelled: a wait whose caller left. invalid: bad input.",
        +      "enum": [
        +        "ok",
        +        "conflict",
        +        "not_found",
        +        "none",
        +        "invalid",
        +        "cancelled"
        +      ],
        +      "type": "string"
        +    },
        +    "task": {
        +      "description": "The task you now own: id, title, description, priority, depends_on, paths, created_by, created_at, updated_at, notes, and state: its status with owner (in_progress), owner and reason (blocked), or by (done).",
        +      "type": "object"
        +    },
        +    "waiting_on": {
        +      "description": "Present when the task's paths overlap what others hold: path, owner. Coordinate before editing those.",
        +      "items": {
        +        "type": "object"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "status"
        +  ],
        +  "type": "object"
        +}
    • Changedtask_update7 fields changed
      • addedInput schema / properties / agent / description
        Added value: +"Your stable agent name."
      • addedInput schema / properties / force / description
        Added value: +"Take or close a task another agent has in progress."
      • addedInput schema / properties / note / description
        Added value: +"A note to append. For `blocked`, this is the reason."
      • addedInput schema / properties / status / description
        Added value: +"One of `todo`, `in_progress`, `blocked`, `done`."
      • addedInput schema / properties / status / enum
        Added value: +[
        +  "todo",
        +  "in_progress",
        +  "blocked",
        +  "done"
        +]
      • addedInput schema / properties / task_id / description
        Added value: +"The task's id, or a unique prefix of it."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "description": "Any result may also carry lost, inbox, inbox_more and persist_error; see guide.",
        +  "properties": {
        +    "message": {
        +      "description": "Human-readable detail, on most outcomes other than ok.",
        +      "type": "string"
        +    },
        +    "owner": {
        +      "description": "On conflict: the agent that has the task in_progress."
        +    },
        +    "since": {
        +      "description": "On conflict: RFC 3339 time that agent took it."
        +    },
        +    "status": {
        +      "description": "ok. conflict: another agent has it in_progress and force was not set. not_found: no such task. invalid: bad status or an ambiguous id prefix.",
        +      "enum": [
        +        "ok",
        +        "conflict",
        +        "not_found",
        +        "none",
        +        "invalid",
        +        "cancelled"
        +      ],
        +      "type": "string"
        +    },
        +    "task": {
        +      "description": "The task after the change: id, title, description, priority, depends_on, paths, created_by, created_at, updated_at, notes, and state: its status with owner (in_progress), owner and reason (blocked), or by (done).",
        +      "type": "object"
        +    }
        +  },
        +  "required": [
        +    "status"
        +  ],
        +  "type": "object"
        +}
  2. 22 tool updatesv1.1.1
    • First observedclaim
    • First observedclaims_list
    • First observedcontract_get
    • First observedcontract_list
    • First observedcontract_publish
    • First observeddecision_list
    • First observeddecision_record
    • First observedmemory_delete
    • First observedmemory_read
    • First observedmemory_search
    • First observedmemory_write
    • First observedmessage_list
    • First observedmessage_send
    • First observednotice_list
    • First observednotice_publish
    • First observedrelease
    • First observedrenew
    • First observedstatus
    • First observedtask_create
    • First observedtask_list
    • First observedtask_pull
    • First observedtask_update

TDQS

A4.5/5.0

Scored across 23 tools

Disambiguation5/5

Each tool maps to a distinct resource/action: lease acquisition, inspection, renewal, and release are separate, and contract, memory, decision, message, notice, and task tools are clearly scoped. Potentially overlapping pairs like contract_publish/notice_publish and memory_write/decision_record are explicitly differentiated in their descriptions.

Naming Consistency4/5

Most tools follow a clear resource_action pattern (contract_get, memory_write, task_update, notice_publish). However, bare verbs and nouns such as claim, release, renew, status, and guide, plus the plural claims_list, break the pattern slightly while remaining predictable.

Tool Count4/5

23 tools is on the heavy side, but the server covers seven distinct coordination primitives: leases, contracts, memory, decisions, messages, notices, and tasks. Each tool has a distinct job, so the count is reasonable for the scope even though it exceeds the typical concise range.

Completeness4/5

The toolset provides a usable lifecycle for each domain: claims support acquire/list/renew/release, memory supports full CRUD plus search, tasks support create/list/pull/update, and contracts support publish/list/get with versioning. Minor gaps such as the absence of a full single-task getter and no explicit contract deprecation are workable through existing update and versioning mechanisms.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables peer-to-peer communication, discovery, shared state, and file coordination between AI coding agents across machines and sessions.
    49 npm
    19
    Elastic 2.0
  • A
    license
    B
    quality
    C
    maintenance
    MCP server that provides a live coordination layer for AI agents, including attributable handoffs, a shared event ledger, atomic work-claiming, and advisory file leases to prevent collisions.
    27
    9
    AGPL 3.0
  • A
    license
    Not graded
    quality
    A
    maintenance
    Use Agent Claim MCP when multiple coding agents share one worktree and you need a tiny local coordination primitive before edits, not a full orchestration framework. It gives agents one job: claim paths, detect collisions, and release ownership so parallel work stops stomping the same files.
    26 npm
    MIT