Skip to main content

Module mock

Module mock 

Source
Expand description

A minimal built-in mock LLM for the observe-to-validate E2E suite (M7). Hidden mode: agentd --internal-mock-llm <addr-file> [script].

Binds a loopback TCP listener on 127.0.0.1:0 and writes the bound host:port into <addr-file> (atomically: tmp + rename) so the launching harness discovers the endpoint by waiting for the file — the same wait-for-path handshake the old unix-socket form had, except the file now carries the address instead of being the socket. The harness then hands agentd --intelligence http://<addr> (loopback plaintext is the dev/test carve-out; production intelligence is HTTPS-only).

Speaks just enough OpenAI-compatible /chat/completions over that listener to drive a real agentic loop without a live model: it reads the request and returns a scripted assistant turn — a final answer or a tool call — switching to a final answer once a tool result appears in the transcript (so the ReAct cycle closes). Scripts: final (answer at once), read (call resource.read then answer), schedule (call the schedule self-tool then answer), subscribe (call the subscribe self-tool then answer), spawn-churn (call subagent.spawn on every turn — never converging — so a run issues a rapid burst of spawns that trips the spawn-rate limiter, RFC 0009 §3.6); slow/hang hold the response to exercise the stuck/deadline detectors. Small enough to ship; it makes the loop + self-* tools observable end to end.

Programmable scripts (agentd 2.0 e2e): file:<path> loads a JSON playbook so a test scripts any conversation without a new built-in:

{ "turns": [ {"tool_calls": [{"name": "memory.set", "arguments": {"key": "k", "value": 1}}]},
             {"content": "done", "usage": {"prompt_tokens": 100, "completion_tokens": 20}} ],
  "match": [ {"when_contains": "\"preflight\"", "content": "{\"intent\":\"task\"}"} ] }

match[] rules are tried first (the first whose when_contains substring appears in the request body answers); otherwise turns[i] answers where i is the number of role: tool messages already in the transcript (clamped to the last turn). A turn carries content (final text) or tool_calls, an optional usage, and an optional delay_ms.

Functions§

run
Serve the mock LLM until the process is killed, announcing the bound loopback address through addr_file. Returns the exit code.