You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
We want cfa-tool to sit as a framework on top of the existing SDKs (Vercel eve / Claude Agent SDK), not as an SDK that competes with them. A tool is written in cfa-tool from the start and chooses which SDK it targets (eve / claude / none). Layers are a cfa-tool concept the SDK never sees. To emit a cfa-tool tool to a target SDK we must translate the cfa result (layer + error envelope) into that SDK's return format, but the mapping is OPEN and unresolved. This issue is a DESIGN-DECISION task: its deliverable is a written design decision, not code. It is NOT ready to implement until the open decisions below are closed.
Scope & Decomposition
Produce a written design decision that closes the open mapping, sufficient to open a follow-up implementation issue with no arbitrary choices. No code in this issue.
Verified SDK reference (against official docs, not memory):
Claude Agent SDK (@anthropic-ai/claude-agent-sdk): tool() + createSdkMcpServer(); the handler returns a CallToolResult with content (required, array of typed blocks), structuredContent (optional, Record<string,unknown>), isError (optional). Two error paths with different semantics: an uncaught throw stops the agent loop (the query fails); isError: true lets the model see the error as data and retry. No native error taxonomy, no native subcommands. Source: code.claude.com/docs/en/agent-sdk.
eve (Vercel, package eve v0.13.0, beta): defineTool (one file per tool); execute(input, ctx) returns a plain domain object; optional outputSchema and optional toModelOutput(output) which returns {type:'text'|'json', value} to project what the model sees; no ok convention, no documented error taxonomy, no subcommands. Source: vercel.com/docs/eve + repo vercel/eve.
Acceptance Criteria
This issue is done when each open decision below is decided and documented.
OPEN DECISIONS (resolve when the task is picked up):
Layer collapse: if the SDK never sees layers, what does cfa-tool emit as the successful result? Both SDKs have a projection mechanism (structuredContent in claude, toModelOutput in eve). Decide: does each layer (L1/L2/L3) map to a distinct shape using those mechanisms, or do all three flatten to the same format and the layer become purely internal/documentation at the SDK boundary? (The answer changes the value of layers when targeting an SDK.)
Error translation: cfa's rich error { ok: false, error, message, detail } vs claude's isError flag + content (and the throw that stops the loop), and eve's lack of a documented error taxonomy. How is the envelope translated without losing cfa's taxonomy?
ok: true/ok: false <-> claude isError: near 1:1 mapping, the only one that maps cleanly. Confirm and document.
Subcommand exposure: no SDK has a native slot. How are subcommands exposed to the SDK? (Non-exhaustive candidates from the docs: one tool per subcommand; a single tool with an enum action param; in eve, multiple tool files / subagents / skills. The axis and the chosen option are open.)
none target: confirm it is the current jsonOutput behavior (pure JSON, no adaptation).
The result is a written design decision sufficient to open an implementation issue with no arbitrary decisions.
Risks & Constraints
Implementing before closing the open mapping injects arbitrary decisions the cfa pattern did not choose. Coupling cfa-tool to the eve/claude APIs (which change; eve is beta v0.13.0) adds maintenance.
[inferred] SDK references are pinned to current versions; revalidate the Claude Agent SDK (unpinned docs) and eve (v0.13.0, beta) before locking the mapping, since their return contracts may shift.
Edge Cases
[inferred] An error raised after partial layer output (e.g. L3 instructions already built) must still produce a coherent SDK error result; decide which path (claude isError vs throw) is used so the loop is not silently killed.
[inferred] The none target must remain the default passthrough so existing tools keep emitting pure JSON unchanged.
Out of Scope
The cfa-tool layer model and error model themselves (already exist / separate spec).
Implementing the adapter (this issue only closes the design).
Problem & Motivation
We want cfa-tool to sit as a framework on top of the existing SDKs (Vercel eve / Claude Agent SDK), not as an SDK that competes with them. A tool is written in cfa-tool from the start and chooses which SDK it targets (eve / claude / none). Layers are a cfa-tool concept the SDK never sees. To emit a cfa-tool tool to a target SDK we must translate the cfa result (layer + error envelope) into that SDK's return format, but the mapping is OPEN and unresolved. This issue is a DESIGN-DECISION task: its deliverable is a written design decision, not code. It is NOT ready to implement until the open decisions below are closed.
Scope & Decomposition
Produce a written design decision that closes the open mapping, sufficient to open a follow-up implementation issue with no arbitrary choices. No code in this issue.
Verified SDK reference (against official docs, not memory):
@anthropic-ai/claude-agent-sdk):tool()+createSdkMcpServer(); the handler returns aCallToolResultwithcontent(required, array of typed blocks),structuredContent(optional,Record<string,unknown>),isError(optional). Two error paths with different semantics: an uncaughtthrowstops the agent loop (the query fails);isError: truelets the model see the error as data and retry. No native error taxonomy, no native subcommands. Source: code.claude.com/docs/en/agent-sdk.evev0.13.0, beta):defineTool(one file per tool);execute(input, ctx)returns a plain domain object; optionaloutputSchemaand optionaltoModelOutput(output)which returns{type:'text'|'json', value}to project what the model sees; nookconvention, no documented error taxonomy, no subcommands. Source: vercel.com/docs/eve + repo vercel/eve.Acceptance Criteria
This issue is done when each open decision below is decided and documented.
OPEN DECISIONS (resolve when the task is picked up):
structuredContentin claude,toModelOutputin eve). Decide: does each layer (L1/L2/L3) map to a distinct shape using those mechanisms, or do all three flatten to the same format and the layer become purely internal/documentation at the SDK boundary? (The answer changes the value of layers when targeting an SDK.){ ok: false, error, message, detail }vs claude'sisErrorflag +content(and the throw that stops the loop), and eve's lack of a documented error taxonomy. How is the envelope translated without losing cfa's taxonomy?ok: true/ok: false<-> claudeisError: near 1:1 mapping, the only one that maps cleanly. Confirm and document.actionparam; in eve, multiple tool files / subagents / skills. The axis and the chosen option are open.)nonetarget: confirm it is the currentjsonOutputbehavior (pure JSON, no adaptation).Risks & Constraints
Implementing before closing the open mapping injects arbitrary decisions the cfa pattern did not choose. Coupling cfa-tool to the eve/claude APIs (which change; eve is beta v0.13.0) adds maintenance.
[inferred] SDK references are pinned to current versions; revalidate the Claude Agent SDK (unpinned docs) and eve (v0.13.0, beta) before locking the mapping, since their return contracts may shift.
Edge Cases
[inferred] An error raised after partial layer output (e.g. L3 instructions already built) must still produce a coherent SDK error result; decide which path (claude
isErrorvs throw) is used so the loop is not silently killed.[inferred] The
nonetarget must remain the default passthrough so existing tools keep emitting pure JSON unchanged.Out of Scope
Source: design session 2026-06-22, spec
docs/specs/proposal-sdk-adapter-layer.md.