Skip to content

Cell - Ta Agents ​

A pi package that comes with Ta (on by default; turn it off in Settings → Extensions of the web client): other coding agents as models to pick. A conversation on CodeBuddy Code, Claude Code or Codex runs every turn on that agent's own harness: its system prompt, tools, context management, subagents and login, so you get the agent as it works with its own models. It is one pi extension (src/extension.ts → extension/index.mjs), with no change to Ta's core; pi can install it too:

bash
pi install npm:@celljs/ta-agents

The agents are reached over the Agent Client Protocol (ACP, stdio):

AgentOffered whenStarted as
CodeBuddy Codecbc or codebuddy is installedcbc --acp
Claude Codeclaude is installednpx -y @agentclientprotocol/claude-agent-acp (the ACP project's adapter, with Claude Code's own login)
Codexcodex is installednpx -y @agentclientprotocol/codex-acp (likewise, with Codex's own login)

CodeBuddy Code works as in its own terminal: in PTC (code mode, its tools called through REPL; it declares mainAgentSupport / toolModeSupport and sets CODEBUDDY_CODE_MODE_ENABLED=1, without which ACP clients get the standard mode only), and a new session has full access (options.mode, which the settings change). npx fetches an adapter the first time it is used; the versions are pinned in the package. Each agent keeps its own login: when it is not signed in, the conversation says which command to run in a terminal (cbc, claude, codex login).

Use ​

Pick one in the model list of the + on the left of the input box, an agent's models are listed by their names, with the agent beside them (Claude-Opus-5.5 codebuddy-code, for example). Each agent is a provider (codebuddy-code, claude-code, codex) whose models are the ones the agent lists; default (the entry named only after the agent) uses the default model set up in the agent. The models are known once the agent ran, and kept in ~/.cache/ta-agents/models.json. The thinking level becomes the agent's own (xhigh is CodeBuddy Code's xhigh or max, for example).

agents in pi's settings.json changes the built-in agents or adds other ACP agents:

json
{
  "agents": {
    "codex": false,
    "claude-code": { "permissions": "ask" },
    "gemini": { "name": "Gemini", "command": "gemini", "args": ["--experimental-acp"] }
  }
}

Fields: name, command, args, env, login (the sign-in command to tell the user), permissions, options (the agent's settings of a new session, by the id or category of the option, such as { "mode": "default" }), clientMeta (_meta of the client's capabilities in initialize). env and options of a built-in agent merge with those of the settings. false turns a built-in agent off. A built-in agent named in the settings is offered even when its program is not found, so it can run another one: the adapters read CLAUDE_CODE_EXECUTABLE (Claude Code's executable) and CODEX_PATH (the codex command), for example for wrappers built on the same code:

json
{
  "agents": {
    "claude-code": { "env": { "CLAUDE_CODE_EXECUTABLE": "/usr/local/bin/tclaude" }, "login": "tclaude login" },
    "codex": { "env": { "CODEX_PATH": "tcodex" }, "login": "tcodex login" }
  }
}

How it works ​

  • A turn: each time pi asks the model, only what the user said since the agent last answered goes to the agent (session/prompt), since the agent keeps its own history. The agent's text and thinking stream as pi's message.
  • Tool calls: the agent uses its own tools; each call is recorded in pi as a call of agent_tool (its arguments are a title, a kind and a target, such as { kind: "execute", target: "npm test" }), so Ta shows it as a line like its own tools, with the agent's output as the result. As soon as a call of kind edit, delete or move names the file it changes (locations, or file_path and the like in its arguments), or brings an ACP diff, the extension emits ta:file-write on pi.events ({ path, before? }, TA_FILE_WRITE_EVENT of ta-protocol), so that ta-changes keeps the file as it was before the agent writes it. When the agent starts a call, the assistant message ends (toolUse); pi "running" agent_tool only waits for the agent to finish the call, and pi's next request goes on with the same turn. some agents (CodeBuddy Code) stream the arguments first, so a call shows once the agent says they are complete (toolArgumentsComplete in _meta, or announcing the call again as pending with them); without such a sign, 1.5 seconds without news of the call, or the agent saying something else, will do; calls started together go in one message and show in parallel. agent_tool is active only while the model is an agent.
  • Sessions: a pi session uses one session of each agent; its id is kept in the pi session (the custom entry ta-agents.session), and reopening the conversation loads it again (session/load). A fork, or going back to an earlier message in pi (/tree), starts a new session of the agent on the next turn and hands it the conversation so far as text; so does switching to an agent in the middle of a conversation (30,000 characters at most).
  • Processes: the sessions of one agent in one directory share a process (one of CodeBuddy Code takes about 650 MB); by directory, because CodeBuddy Code runs commands where it was started rather than in the directory of the session. A process stops after 10 minutes without a turn, and starts again, loading its sessions, when it is needed. It keeps pi's process alive only while a request waits for its answer, so pi -p exits once it answered.
  • When the agent goes on by itself: after a background task, an agent may start a turn on its own (CodeBuddy Code starts it with unsolicitedTurn in a session_info_update and ends it with session_end; other agents give no end, and the turn ends after 3 quiet seconds). The extension sends pi a message that is not shown, which starts a pi turn that shows it.
  • When the user talks while the agent works: ACP has no way to steer a turn, so it is kept and sent as the next turn as soon as this one ends. Stopping sends session/cancel; the next turn waits for the agent to end the cancelled one (5 seconds at most).
  • Permissions: as in pi, nothing is held back: a permission request of the agent is answered "allow once". With permissions: "ask" the user picks in the UI. The agent's own permission mode (CodeBuddy Code's settings, for example) still applies.
  • Compaction: the agent manages its context. pi's automatic compaction is cancelled for conversations with an agent; compacting by hand (Compact in the + menu, or /compact) sends /compact to the agent, which compacts with its own command.
  • Title: when the agent names its session (session_info_update) and the conversation has no name yet, it becomes the conversation's name, also when the title comes late.
  • When a turn ends: usually when the agent answers session/prompt. CodeBuddy Code answers only once it named the session (about 5 seconds later), so its turn ends when the phase it reports (agentPhase in _meta) goes from working back to idle, not counting phases of requests of earlier prompts (by requestId in _meta: the end of a /compact, for example); the next prompt waits for the answer to the one before (15 seconds at most).
  • Language of errors: the language of Ta's pages (which they tell the Ta service with TaSettingsServer.setLanguage: TA_LANGUAGE of the process), else the computer's (LC_ALL, LC_MESSAGES, LANG, else Node's locale).
  • Slash commands: /command goes to the agent as it is. Commands that only act in the agent's own interface (/skills, /doctor, /clear of CodeBuddy Code) return nothing over ACP; a line then says it ran with nothing back, so that it does not look ignored. After /compact, CodeBuddy Code returns nothing for its local commands (/cost, /todos) either: that is on its side.
  • Usage: the tokens the agent reports (usage_update) are put on the last message of each turn. The adapters of Claude Code and Codex report the context only, no output tokens, so the output shows 0.
  • Several sessions: the sessions of a process share one model runtime, where the provider registered last replaces the others; its streamSimple finds the extension of the session that asks by the sessionId pi passes. agents of settings.json is read when the extension loads, so that a session resumed on an agent's model finds it.
  • ACP dialects: CodeBuddy Code streams the arguments first (_meta.toolArgumentsComplete says they are complete); Codex puts the output of commands in _meta.terminal_output_delta, its result being only the exit code; Claude Code's result is in the content of its last update.

Not yet ​

  • Conversations in ssh:// directories (the agent runs on this computer and cannot see remote files).
  • The agent's own slash commands (available_commands_update) are not in the + menu yet; typing /command in the box sends it to the agent as it is.
  • The client file system and terminal of ACP are not offered: the agent reads and writes files and runs commands with its own tools.