Skip to content

Tau — Reference

Cognition × Application

Four packages, five distributions, three wire protocols, one extension API. This page is the map; each package has its own page below it.

Draft

Built for lookup, not narrative reading. Written against the running code rather than against the source repo's own design docs, several of which predate the current provider layer. tau --help is the exact contract for every CLI table here; treat a disagreement as this page being stale.

The stack

The four packages and the one-way boundaryFour labelled boxes stacked down the left of the figure, each with a gloss to its right, and one red horizontal rule across the whole width. At the top, above the rule, sits tau underscore coding underscore agent, glossed as the tau command and the Textual TUI, and noted that c l i dot p y line 519 is the only import of the app so that tau dash p and tau dash dash mode r p c load no interface library. The red rule below it is marked the one-way boundary, with the gloss that nothing below the line imports anything above it. Under the rule are three more boxes. tau underscore agent underscore core holds the agent loop, tools, sessions and extensions, and assumes no terminal. tau underscore jmfts, drawn in a lighter outline because it is optional, sends an arrow up into tau underscore agent underscore core. tau underscore llm sits at the bottom holding the three wire protocols and the message, tool and streaming-event types, and depends on pydantic and httpx and nothing else. A downward arrow runs from the coding agent across the red rule into the agent core, and a second downward arrow runs from the agent core past the jmfts box into tau underscore llm. Every arrow points down; none points up.interfacetau_coding_agentthe tau command, and the Textual TUIcli.py:519 is the only import of the app,so tau -p loads no interface librarythe one-way boundarynothing below this line imports anything above itheadlesstau_agent_corethe agent loop, tools, sessions, extensionsno textual, no stdin or stdout assumptionstau_jmftsoptional · --store jmftsan entry becomes a documenttau_llmthree wire protocols, and the message,tool and streaming-event typesdepends on pydantic and httpx, nothing else
Read the arrows as "imports". Every one points down, and the red rule is the reason the split is worth having rather than a filing convention: because nothing under it reaches up, the headless half runs with no terminal libraries installed at all — measured at 15 packages and 13 MB, against 27 and 31 MB with [tui]. The same property is what lets tau_agent_core be embedded in a host process, driven over stdio, or run under the TUI without knowing which.

Packages

Each is installable on its own. The ffwf- prefix is not decoration: tau-ai and tau-llm on PyPI are unrelated third-party projects, so pip install tau-llm fetches someone else's code.

Distribution Imports as What it is
ffwf-tau — The guessable name. A meta package: depends on ffwf-tau-coding-agent[tui] at the same version and nothing else.
ffwf-tau-llm tau_llm Wire protocols, message and tool types, streaming events.
ffwf-tau-agent-core tau_agent_core Agent loop, tools, sessions, extensions, RPC. Headless.
ffwf-tau-coding-agent tau_coding_agent The tau command and the Textual TUI.
ffwf-tau-jmfts tau_jmfts JMFTS-backed session store. See Tau + JMFTS.

The meta package is the front door — the guessable name, and it pins the top of the stack at the same version:

pip install ffwf-tau

Installing the top of the stack directly pulls the rest:

pip install 'ffwf-tau-coding-agent[tui]'

The meta deliberately does not pull [jmfts] — that store needs a running server, so it stays an opt-in extra.

Everything past the headless core is an extra, and each one reports its own absence with the install command rather than a traceback:

Extra Adds Needed for
ffwf-tau-coding-agent[tui] textual, rich the interactive TUI. tau -p and tau --mode rpc run a full turn without it.
ffwf-tau-coding-agent[jmfts] ffwf-tau-jmfts --store jmfts.
ffwf-tau-agent-core[bus] nats-py the built-in nats_bus extension.
ffwf-tau-agent-core[testing] pytest importing tau_agent_core.testing.
ffwf-tau-llm[anthropic] anthropic calling Anthropic (api: "anthropic-messages").
ffwf-tau-llm[google] google-genai calling Gemini or Gemma (api: "google-generative-ai").

The two vendor SDKs import lazily, on the first request rather than at module import, so a plain install pulls neither and import tau_llm works without them.

The install puts two console scripts on PATH — tau and ffwf-tau, the same entry point behind each. Type tau; write ffwf-tau in scripts, systemd units and Dockerfiles. See the DevOps Manual for why.

Where each subject lives

Page Covers
tau_llm The three wire protocols, the two registries and the pool, Model, message and content types, streaming events, tool definitions, reasoning signatures.
tau_agent_core The turn loop and its two event vocabularies, submit() and the one door, sessions as a tree, the SDK entry point, project context files, compaction.
Extensions The ExtensionAPI surface, the hook vocabulary, discovery and collision rules, the bus capability grant.
RPC The JSON-RPC verb tables, the two answers a submission gets, and the seven verbs τ declines.
tau_coding_agent The four run modes, the full CLI flag table, config.json, and what the TUI is actually made of.
API Every name, its signature, its parameters — generated from the source's own docstrings rather than written here.

The five pages above are prose: they say how the pieces fit and which distinctions are easy to get backwards. API is the other kind of reference — one entry per marked object, exported from the τ repository by a script, so it says what the code says and no more.

Three things that are easy to get backwards

A tool call is transformed four times on its way from HTTP bytes to a rendered widget — provider ToolCall, then a message dict block, then a backend info dict, then a widget. When tool calling misbehaves, trace the arguments value through all four hops rather than reading any one of them. tau_llm and tau_agent_core each own two of those hops.

api and provider are different questions. api is which wire protocol to speak; provider is which vendor, and therefore which base URL and which credential. Many vendors share one protocol, which is why they are two fields and two registries. See tau_llm.

Tool argument validation is hand-rolled. validate_tool_arguments checks type and required from a plain-dict schema and nothing else — no minLength, no minimum, no enum. Writing one of those into a tool schema looks enforced and is silently ignored. See tau_llm.