Context
During sessions#50 step 2 review, Or floated the idea of a builder-style API for harnesses:
harness
|> Cli.Harness.Pi.with_model("claude-opus-4-6")
|> Cli.Harness.Pi.with_cwd("/tmp")
|> Cli.Harness.Pi.with_system_prompt("/tmp/prompt.txt")
|> Cli.Harness.Pi.run(message)
vs the current flat-args protocol:
harness.build_command(message, model, system_prompt_file, session, timeout, harness_opts)
The ambition: develop a universal agent harness API — a superset over what pi, claude, and future harnesses each accept, with adapter-specific knobs exposed cleanly (e.g. claude's --dangerously-skip-permissions stays on claude only).
Why deferred
Step 2 kept the flat-args protocol because:
- Bash doesn't do builders well. We'd have builder semantics in Python + Elixir but flat args in bash — cross-language drift that the step 2 self-review specifically flagged as a risk.
- Designing in the dark. The builder's value is adapter-specific surface, but we only have one adapter today. What pi and claude actually need to differ on is what step 3 will reveal.
- Scope. Step 2 already bundles resolver + wake reshape + three-language dispatchers. An API redesign belongs in a focused follow-up.
When to revisit
After step 3 (claude) lands, if any of these are true:
- Engine ends up branching on harness type to pass different args
- Adapter-specific opts leak into generic call sites
build_command's 6-arg signature grows or splits per adapter
- Claude has config that doesn't map cleanly onto pi's shape
That's the evidence-based signal. Until then, flat args are adequate and the builder is speculative.
Open questions (to answer with claude in hand)
- Does the bash layer need builders at all, or can it stay flat while Python/Elixir get richer APIs? (Bash mostly writes JSONL entries; it may not need composition.)
- Is the right level of abstraction
harness.build_command → harness.run(config) with an explicit Config struct, or a pipe-chain of with_* transformers?
- Can the universal API be inferred from the union of pi + claude's opts, or does it need to be designed top-down?
Not a step 3 blocker
File this under "things to notice while writing claude, not things to build first."
Context
During sessions#50 step 2 review, Or floated the idea of a builder-style API for harnesses:
vs the current flat-args protocol:
The ambition: develop a universal agent harness API — a superset over what pi, claude, and future harnesses each accept, with adapter-specific knobs exposed cleanly (e.g. claude's
--dangerously-skip-permissionsstays on claude only).Why deferred
Step 2 kept the flat-args protocol because:
When to revisit
After step 3 (claude) lands, if any of these are true:
build_command's 6-arg signature grows or splits per adapterThat's the evidence-based signal. Until then, flat args are adequate and the builder is speculative.
Open questions (to answer with claude in hand)
harness.build_command→harness.run(config)with an explicitConfigstruct, or a pipe-chain ofwith_*transformers?Not a step 3 blocker
File this under "things to notice while writing claude, not things to build first."