feat(layer3): run Claude meta-agent via Agent SDK#58
Merged
jonathansantilli merged 1 commit intomainfrom Apr 23, 2026
Merged
Conversation
Previously layer 3's Claude path shelled out to the `claude` binary
via `spawn()`, passing the prompt as argv and parsing the
`--output-format json` stdout envelope. That worked but limited us to
whatever the CLI exposes and double-encoded the prompt through shell
argument escaping. It also obscured auth: the user had to run `claude
login` out of band and we had no visibility into which account was in
use.
Switching Claude over to `@anthropic-ai/claude-agent-sdk`:
- New provider `src/layer3-dynamic/claude-sdk-provider.ts` calls
`query({ prompt, options })` and collects the `SDKResultSuccess.result`
string as stdout, mapping our readOnly flag to
`{ maxTurns, permissionMode, tools, allowedTools }` that mirrors the
old CLI flag set (no tools / max-turns 1 for regular scans;
Read+Glob+Grep under plan mode / max-turns 10 for read-only).
- Timeout preserved: an AbortController aborts the query after the
same budget the sandbox spawn used (30s default, overridable).
- Auth follows the SDK's default precedence — ANTHROPIC_API_KEY if
set, otherwise the SDK reuses whatever the bundled Claude binary
reads from `~/.claude/settings.json`. No explicit key plumbing,
which is the whole point.
Dispatcher in `cli.ts` routes `metaTool === 'claude'` to the SDK and
leaves Codex + generic/OpenCode on the existing spawn path. The
consent preview in `command-builder.ts` still produces the CLI-shape
preview string so the user sees a familiar command when approving the
scan; only execution changed.
Codex SDK migration is deferred — the Codex SDK's auth fallback has
a live bug (openai/codex#7144 — 401s despite fresh ~/.codex/auth.json)
that needs validation in our environment before we adopt it.
github-actions Bot
pushed a commit
that referenced
this pull request
Apr 23, 2026
# [0.16.0](v0.15.2...v0.16.0) (2026-04-23) ### Features * **layer3:** run Claude meta-agent via Agent SDK instead of CLI spawn ([#58](#58)) ([5e3c6c8](5e3c6c8)), closes [openai/codex#7144](openai/codex#7144)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
claudeCLI spawn in layer 3 with@anthropic-ai/claude-agent-sdk@^0.2.118, so Claude meta-agent analysis uses the typed SDK instead of argv + stdout JSON parsing.claude login— the SDK spawns the bundled Claude binary which reads~/.claude/settings.json.ANTHROPIC_API_KEYstill overrides if set.What changed
src/layer3-dynamic/claude-sdk-provider.ts— new module, wrapsquery({ prompt, options }), maps ourreadOnlyflag to{ maxTurns, permissionMode, tools, allowedTools }that mirror the old CLI flag set, collectsSDKResultSuccess.resultas thestdout-shaped string soparseMetaAgentOutputkeeps working unchanged, usesAbortControllerfor the same 30s timeout budget.src/layer3-dynamic/command-builder.ts—MetaAgentCommandgainsprompt+readOnlyfields so SDK runners can pick them up without re-parsing argv. The CLI-shape preview string is unchanged, so the consent prompt still shows the familiarclaude --print …command.src/cli.ts—runMetaAgentCommandWithSandboxbranches oncontext.agent.metaTool:'claude'→ SDK, everything else → existing spawn.Test plan
npm test— all 722 tests pass (18 layer-3 test files, 99 layer-3 tests included)npx tsc --noEmit— cleancodegate scan --deep) on a machine withclaude loginalready done, verify Claude path works withoutANTHROPIC_API_KEYsetANTHROPIC_API_KEYset and no CLI login, verify API-key fallback works--read-onlymode, verify the Read/Glob/Grep tools are usable and writes are blocked (plan permission mode)CODEGATE_META_AGENT_TIMEOUT_MS=1), verify we get a 124 exit-shape result and don't hang