devin run choosing its own calls across native, built-in, skill and
MCP tools.Most agent CLIs offer only one-shot -p mode, and for many hosts that is enough.
examples/onnx-in-process shows the seam for a local model; a local agent CLI is
the other common case and has nothing equivalent, so every host hand-rolls the same
adapter.
Three findings from the working implementation are worth more than the feature itself.
1. The CLI is configuration, not code. The presets differ only in argv:
devin --prompt-file {{file}} -p --permission-mode dangerous [--model M]
claude -p {{prompt}} [--model M]
copilot -p {{prompt}} --log-level none --no-color [--model M]
codex exec --skip-git-repo-check --output-last-message {{out}} [-m M] {{prompt}}
Prefer a prompt file where the CLI supports one — no length limit, no quoting
hazard. codex additionally needs "read the answer from this file, not stdout".
2. Pass the request body through verbatim. A CLI has no tool-call channel, so the
adapter needs a response contract. What worked was handing the CLI the exact
assembled OpenAI body inside an <openai_request> envelope and asking for an
<openai_response> back. Byte-for-byte passthrough means tools, tool_choice,
response_format and anything toolnexus adds later reach the model without the
adapter learning about them first. Re-rendering as prose loses information: the
reporter's first version dropped tool_call_id, so the model could not tell which of
several parallel results it was looking at.
3. Validate and repair — never massage. Real drifts observed from a live model:
kind:"answer" with a populated tool_calls array. Dispatch on the declared
finish reason and the call is silently dropped. What the message contains must win.content as an object instead of in argumentsarguments as a JSON-encoded string rather than an objectThe fix that held: parse strictly; on failure resend the same request with the specific complaint appended, up to a small repair budget, then error. Degrading a malformed reply into plain content is how a dropped tool call becomes a confidently wrong answer.
Ship a CLI model source as a Generate (same seam as ADR 0031), with an argv
template, a file-or-argv prompt channel, a stdout-or-file response channel, the
verbatim-body envelope, strict parse + bounded repair, and retries off by default
(ADR 0029).
The open question this ADR does not settle: whether the four presets ship in the library or as an example. A preset is a compatibility promise about someone else's CLI flags, which change without warning and cannot be tested in CI.
kind:"answer" + tool_calls case specifically not dropping the call.Can you improve this documentation?Edit on GitHub
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |