Expand description
The model adapter: an agent CLI on the path, prompt on stdin, completion on stdout (ADR 0016; one argv per agent, ADR 0033).
llm is the port; this is its one implementation, on the pattern of
forge/forgeio. Nothing else in the engine may reach into subprocess
machinery: grouping and the pipeline consume LlmBackend from llm, the
application layer builds a CommandBackend here and hands it over, and the
layering test names this file as an adapter so that the port’s file is
checked as domain.
There are five agents, one constructor each, and the trait did not move to make room for them (ADR 0033). What differs between them is the argv, and the part of the argv that matters is how each one is stopped from writing:
- An allowlist —
claude_cli,copilot_cli. The agent may run the named tools and nothing else, and the fetch command is one of them. - An OS sandbox —
codex_cli,droid_cli. The agent may run anything and the kernel refuses the writes, so there is no allowlist to derive andfetchdoes not appear in the argv. - Nothing —
pi_cli. Pi ships no sandbox and no per-command allowlist, and the shell tool it needs to fetch is the one that also lets it write. That is a decision with a reason, recorded in ADR 0033 and in the constructor, andconfig::Agent::read_onlyis how a caller tells a user about it.
Adding a sixth means a constructor here, a variant in config::Agent, and
an arm in the application layer’s backend_from. The compiler asks for the
last two; this comment is the only thing that asks for the boundary.
Structs§
- Command
Backend - A subprocess backend: prompt on stdin, completion on stdout.