Read this part first: you probably do not need an adapter.
There are three ways to put CTRLRun in front of a consequential action and only one is an
adapter. @protect covers anything running in this process — a raw OpenAI call, a LangChain
tool, a hand-rolled loop — with a decorator and no framework support at all. The MCP gateway
covers anything reaching its tools over MCP, in any language. An adapter exists for exactly one
reason: to route an approve decision through the framework's own interrupt instead of
raising past it, so that a human answers where they already answer.
A framework with no human-in-the-loop primitive has nothing for an adapter to reuse and does
not need one. That is the answer to "what about X?" for every X.
The list
Two reference adapters ship: LangGraph (reusing interrupt() and the
checkpointer) and OpenAI Agents SDK (reusing the tool-approval
interruption). The roadmap names seven more, and says the order they arrive in is demand, not
the list:
- Google ADK
- Microsoft Agent Framework (Python)
- Claude Agent SDK (Python)
- PydanticAI
- CrewAI
- Strands Agents
- LlamaIndex
Comment with the one you want, and say whether you want to write it or use it. Both are
useful signal. Claim one before you start.
What writing one involves
docs/adapters.md §"Writing one" is the short version and
docs/SPEC-v0.5.md is the contract. The rules that bite:
- Never a second approval path beside the framework's own. No prompt, no queue, no resume
token, no approval UI of the adapter's own. Two places to say yes is one place nobody is
watching.
- An adapter never writes a grant. It returns an
ApprovalAnswer; InterruptApprovalProvider
records it, through the same calls ctrlrun approve makes.
- An adapter never constructs a
Control and never supplies a Principal. The operator
wires it. §2.3 has the whole never-list with a reason on every row.
- No
auto_approve, no dry_run, no development mode that grants.
- Run the conformance kit and report every suite in the README as
pass or
not_applicable with the reason. Not applicable is not a pass, and no adapter describes
itself as "conformant".
- It ships as its own distribution under
adapters/, on its own version line
(adapters-crewai-1.0, never a kernel version), and it gates no kernel release.
- An adapter is an entry point, so it gets a review by somebody who did not write it. Five
defects were found that way in one of the two reference adapters.
docs/adapters.md also carries the fourteen questions a session writing a third adapter against
the contract alone could not answer — worth reading before you hit the fifteenth. If you hit
one, that is a defect in the contract and it gets fixed in the contract, not worked around in
your adapter.
Read this part first: you probably do not need an adapter.
There are three ways to put CTRLRun in front of a consequential action and only one is an
adapter.
@protectcovers anything running in this process — a raw OpenAI call, a LangChaintool, a hand-rolled loop — with a decorator and no framework support at all. The MCP gateway
covers anything reaching its tools over MCP, in any language. An adapter exists for exactly one
reason: to route an
approvedecision through the framework's own interrupt instead ofraising past it, so that a human answers where they already answer.
A framework with no human-in-the-loop primitive has nothing for an adapter to reuse and does
not need one. That is the answer to "what about X?" for every X.
The list
Two reference adapters ship: LangGraph (reusing
interrupt()and thecheckpointer) and OpenAI Agents SDK (reusing the tool-approval
interruption). The roadmap names seven more, and says the order they arrive in is demand, not
the list:
Comment with the one you want, and say whether you want to write it or use it. Both are
useful signal. Claim one before you start.
What writing one involves
docs/adapters.md§"Writing one" is the short version anddocs/SPEC-v0.5.mdis the contract. The rules that bite:token, no approval UI of the adapter's own. Two places to say yes is one place nobody is
watching.
ApprovalAnswer;InterruptApprovalProviderrecords it, through the same calls
ctrlrun approvemakes.Controland never supplies aPrincipal. The operatorwires it. §2.3 has the whole never-list with a reason on every row.
auto_approve, nodry_run, no development mode that grants.passornot_applicablewith the reason. Not applicable is not a pass, and no adapter describesitself as "conformant".
adapters/, on its own version line(
adapters-crewai-1.0, never a kernel version), and it gates no kernel release.defects were found that way in one of the two reference adapters.
docs/adapters.mdalso carries the fourteen questions a session writing a third adapter againstthe contract alone could not answer — worth reading before you hit the fifteenth. If you hit
one, that is a defect in the contract and it gets fixed in the contract, not worked around in
your adapter.