cloudflare / cloudflare/agents
codemode: support argument-aware approval decisions before durable pause
- Dominant language
- TypeScript
- Stars
- 5.6k
- Forks
- 711
- Avg merge
- 1d 20h
- Merged PRs (30d)
- 53
Description
## Summary
Code Mode durable approvals currently support only a static `requiresApproval: boolean` annotation. Connectors need a way to validate and classify a call from its actual arguments **before** `runtime.decide(...)` records or pauses it.
This remains the behavior in `@cloudflare/codemode` 0.5.1. `buildConnectorBindings` reads `annotation?.requiresApproval`, calls `runtime.decide(...)`, and only then calls `connector.executeTool(...)`. `ToolSetConnector` also documents that a function-valued AI SDK `needsApproval` cannot be evaluated and is therefore conservatively always approval-gated.
## Use case
A connector exposes one GraphQL operation tool:
```ts
graphql({ document, variables })
```
The payload may contain:
- a query, which should execute immediately;
- a mutation, which should pause for approval;
- an invalid, multi-operation, ambiguous, or subscription document, which should be rejected before any approval is created.
With the current API, marking the tool `requiresApproval: true` unnecessarily gates every query. Leaving it untagged lets mutations run. Validating in `executeTool` is too late: the durable runtime has already made and persisted its approval decision.
The same problem applies to tools whose sensitivity depends on a target, action, or argument value.
## Suggested API shape
One option is a connector hook:
```ts
async preflightTool(method, args, ctx) {
// May validate and throw. Must not perform a side effect.
return { requiresApproval: classify(method, args) };
}
```
The durable binding would invoke it before `runtime.decide(...)` and use its result as an override of the static annotation. If preflight throws, the call should fail without creating a pending approval record.
Alternatively, `requiresApproval` could accept an async predicate over the arguments, provided it runs at that same pre-decision boundary.
## Required semantics
- Runs before a pending approval is durably recorded.
- Can reject invalid input without producing an approval request.
- Cannot execute the underlying action or other side effects.
- Has documented replay behavior so an approved action cannot change classification or arguments on resume.
- Preserves the current static boolean behavior by default.
## Related issue
#1148 covers the broader Code Mode approval design and is closed. Durable per-action pause/replay now exists; this issue is specifically about the remaining argument-aware decision boundary.
Contributor guide
Assessment
This issue has not been assessed yet.