Skip to content

Tools & Annotations ​

The complete list comes live from tools/list. Below are the most important concepts for working with the list/task tools.

Filters on list_list_items ​

Server-side filters save you from post-filtering and reduce the response size:

ParameterEffect
stateopen / done / all
assigned_to_meonly items assigned to me (no get_me needed)
due_within_daysdue soon (including overdue)
due_beforedue before an ISO date
sortpriority / due_date / created / modified
compactlean response (fewer tokens)
json
{"name":"list_list_items",
 "arguments":{"state":"open","assigned_to_me":true,"compact":true}}

Useful dedicated tools ​

  • get_my_open_items — "What's on my plate?" (overdue → due → priority)
  • complete_list_item / complete_list_items — check off (single/bulk)
  • list_recent_changes — sync/polling: what has changed since since
  • get_metadata — valid status/priority/scope values
  • get_item_dashboard — a task's dashboard page (requirements, outline) with the numbering the UI shows; get_list_item does not include it
  • search_ai_messages — search/filter the Claude Code AI chat history
  • get_ai_chat_history — read the full AI chat history of an item (no truncation)
  • get_item_ai_status — run state of an item: running / waiting / done / crashed, and since when
  • get_item_ai_summaries — read the closing summaries of runs (counterpart to post_activity_summary)

search_ai_messages ​

Searches/filters the team's Claude Code AI chat history (conversations attached to list items/lists):

ParameterEffect
queryfree-text search in the message content (optional — without query it just filters/lists)
listIdrestrict to a list — UUID, SID, or list number ("177"/"#177")
itemIdrestrict to a single item — UUID, SID, or "#<listNum>.<itemNum>" (e.g. "#177.252", as shown in the UI/commit titles); a bare item number only works together with listId, since list_items.num is only unique within a list
userIdonly conversations created by this user
roleuser / assistant / tool
dateFrom / dateTodate range (ISO 8601)
limit / offsetpagination (max 200)
json
{"name":"search_ai_messages",
 "arguments":{"itemId":"#177.252","query":"rate limit","role":"assistant"}}

Visibility is hard-wired, not a role bypass: a conversation is either public (visible to anyone with access to the underlying item/list) or private (default — visible only to its own creator, no bypass for admin/owner). Details: public-api/docs/MCP-TOOL-AI-MESSAGES.md.

get_ai_chat_history ​

Reads the full AI chat history of a single item — across all its threads, with the complete message content instead of a truncated snippet:

ParameterEffect
itemIdUUID or SID of the item (required)
dateFrom / dateTodate range (ISO 8601) — restrict this so you don't have to load the entire history every time
json
{"name":"get_ai_chat_history",
 "arguments":{"itemId":"<UUID>","dateFrom":"2026-07-04T00:00:00Z"}}

Same visibility rule as search_ai_messages (public vs. private per thread, no role bypass). Details: public-api/docs/MCP-TOOL-AI-CHAT-HISTORY.md.

get_item_ai_status ​

Reads the run state of one or more items — the channel to poll while another item works on an order. get_ai_chat_history tells you what a run said; this tells you whether it is still running.

ParameterEffect
itemIdsUUID, SID or reference #<listNum>.<itemNum> (e.g. #216.114), max 200
listIdAlternative: every item of a list that has an AI thread. UUID, SID or #<listNum>

One state per item to branch on — precedence waiting > running > queued > error > done > idle > no_thread:

stateMeaning
waitingThe run is waiting for an answer (questionText says what for). Beats running, because it is the reason nothing is progressing
runningRunning, heartbeat fresh
staleThe DB says "running" but the last sign of life is older than staleAfterMs (35 min) — treat as probably dead
queuedOrder armed but not started (pending orders deliberately never time out)
needs_decisionThe run finished, the task did not: a decision is missing (decisionText). Answering means placing a new order — unlike waiting, where a live run is paused on a dialog. Set by report_decision_needed
error / donefinished; errorMsg, doneAt
idleThread exists, nothing running right now
no_threadNo AI has ever worked on this item (for you)

Plus statusAt / doneAt / liveAt — the only timestamps of a run that survive a restart. list_recent_changes and list_items.modified are blind to AI runs (see api/lib/claudeCode/util/aiMetaTimestamps.js) and cannot be used for this.

json
{"name":"get_item_ai_status",
 "arguments":{"itemIds":["#216.196","#216.199"]}}

A projection of api/lib/claudeCode/thread/items.js — the same derivation that feeds the AI pill on the item. Two differences: it cleans up nothing (a read tool does not write; orphaned runs are reported as stale instead of being swept away silently), and the heartbeat is checked for freshness. Run state is per creator — other people's runs are not visible.

report_decision_needed ​

The write path to needs_decision. An unattended run (started from a queued order, nobody watching) must not use ask_user: nobody sees the dialog and the run hangs until the stale sweep. It calls this tool instead, finishes everything that does not depend on the decision, and ends with the same findings in text.

ParameterEffect
itemIdUUID, SID or #<listNum>.<itemNum>
decisionWhat has to be decided, with the options — written so it can be acted on without reading the transcript
resolvedtrue clears an existing note (the decision has been made)
json
{"name":"report_decision_needed",
 "arguments":{"itemId":"#216.114","decision":"PR workflow or auto-merge? Both touch finalizeWorktree."}}

In an interactive session use ask_user instead — a human is present there, and answering continues the same run without rebuilding its context.

Why the tool is needed at all: findings that live only in the closing message do not exist for a machine. The run ends normally, its queue row goes to done, and the status channel reported done — an orchestrator considered the task finished although its own summary said otherwise (observed in the field, #216.197). Deliberately no pattern matching on model output: a matcher over free-form text fails silently as soon as the wording drifts.

A new run on the same item clears the note automatically.

get_item_ai_summaries ​

Reads the closing summaries from the Activity feed (list_history, action ai_summary) — the read side of post_activity_summary. The right channel for an orchestrator: a few sentences per item instead of a whole transcript.

ParameterEffect
itemIdsUUID or SID, max 200
listIdAlternative: every item of a list that has a summary
sinceOnly summaries from this timestamp on (ISO 8601) — use when polling
json
{"name":"get_item_ai_summaries",
 "arguments":{"itemIds":["<UUID>"],"since":"2026-08-23T07:00:00Z"}}

There is exactly one entry per item and author: a later run overwrites its own summary and refreshes created. For the history, use get_ai_chat_history. No creator filter — the Activity feed is team-visible in the UI, and post_activity_summary writes nothing for a private conversation anyway; isOwn shows the origin.

Profiles & progressive disclosure ​

The tool schema block goes into every request an agent makes — and one turn consists of several requests. Carrying all tools permanently therefore costs tokens at every step. A client can request a curated profile:

x-liza-mcp-profile: agent
ProfileContents
(no header)all role-permitted tools
agentthe tools a coding agent needs in almost every run: read & change lists/items (incl. bulk), post_activity_summary, get_me, get_widget_spec, search_memory/save_memory
onboardingminimal set for the onboarding guide: check off items, create lists/items, invite_user, search_docs, get_me, post_chat_message

Everything outside the profile stays reachable through two meta tools:

ToolPurpose
list_liza_toolsCatalogue of the tools not loaded, with description and input schema. Optional query filter (e.g. "crm", "calendar").
call_liza_toolInvokes any tool by name: { name, arguments }. Role and argument schema are checked exactly as for a direct call.
json
{"name":"call_liza_tool",
 "arguments":{"name":"schedule_task",
              "arguments":{"title":"Weekly report","action_type":"reminder",
                           "rrule":"FREQ=WEEKLY;BYDAY=MO","message":"Write the report"}}}

This keeps the schema budget small without making any tool unreachable. A client without token worries simply omits the header.

Context headers ​

Three optional headers tell the server which conversation a call comes from. Tools use them as defaults instead of forcing you to pass them:

HeaderEffect
x-liza-conversationCurrent AI conversation (scope_key). schedule_task uses it to plan "for this conversation" without the client knowing an ID.
x-liza-providerThe conversation's AI engine (claude, codex, liza, …). Default provider for scheduled AI tasks.
x-liza-modelThe concrete model. Stored as ai_model on chat blocks the AI posts and shown in the UI.

Annotations ​

Every tool carries behavior hints in tools/list, so that clients can allow read tools automatically and warn before destructive ones:

ToolType
list_list_itemsread-only
update_list_itemwrite · idempotent
delete_list_itemdestructive

readOnlyHint, destructiveHint, idempotentHint, openWorldHint.

Pagination & compact ​

All list tools support compact:true. Paginated tools return has_more — after that, increase offset until has_more:false.