Control Write Safety
Write operations like merging a PR or closing an issue can have irreversible consequences. The SDK provides an approval layer that intercepts mutations before they execute.
Configure write safety and approvals
For TanStack AI, boolean policies use native tool approval. Auto approval uses the GitHub middleware and a shared interrupt registered on the server and client. Follow the TanStack approval setup.
Require approval for all writes
By default, every write operation requires explicit approval. You don't need to pass any extra option:
import { createGithubTools } from '@github-tools/sdk'
const tools = createGithubTools()
Auto approval
With requireApproval: 'auto', the agent stops asking about routine writes the user clearly asked for:
import { createGithubAgent } from '@github-tools/sdk'
const agent = createGithubAgent({
model: 'anthropic/claude-opus-5.5',
preset: 'issue-triage',
requireApproval: 'auto',
})
Before each call to a low-risk write tool, a fast evaluation model scores two things. The first is how costly the call would be if it were wrong. The second is whether the latest user message asked for this exact action. The call runs only when both checks pass. Otherwise the user is asked as usual, so a comment the model decided to post because an issue body told it to still waits for a human.
'auto' covers labels, assignees, reactions, comments, review-thread replies, reviewer requests, notification reads, and workflow re-runs (AUTO_APPROVAL_TOOLS). Merges, file writes, deletes, releases, and other write tools keep requiring approval. You can opt any single tool in or out:
createGithubTools({
requireApproval: {
addLabels: 'auto',
addIssueComment: 'auto',
updateIssue: 'auto',
mergePullRequest: true,
},
})
'auto' works with createGithubTools, createGithubAgent, generateText, and streamText, and needs ai 7.0.105 or later. It is not available on createDurableGithubAgent.
Tune auto approval
The defaults work without configuration. To change them, use evaluation:
createGithubAgent({
model: 'anthropic/claude-opus-5.5',
requireApproval: 'auto',
evaluation: {
maxRisk: 1, // 0 negligible, 1 visible but reversible, 2 hard to undo
minIntent: 0.6, // probability the user asked for this exact call
model: 'typesafe-ai/jev', // any AI SDK evaluation model
},
})
The values shown are the defaults. The default model is TypeSafe's Jev, called through AI Gateway. See Auto presets and approval with Jev for both 'auto' modes together.
When the evaluation model fails
If the evaluation call fails, for example because the model is not enabled for your AI Gateway project, the team is out of credits, or the gateway is rate limiting, the call asks for approval as if 'auto' were true. The agent keeps running, and a github_tools.EVALUATION_FAILED warning with the gateway error as cause is logged through console.warn.
Disable approval in trusted environments
In CI pipelines or automated workflows where human review happens elsewhere (e.g. PR-based), you can disable approval entirely:
import { createGithubTools } from '@github-tools/sdk'
const tools = createGithubTools({
requireApproval: false,
})
Configure approval per operation
For nuanced policies, enable approval selectively. This example approves destructive actions but allows comments freely:
import { createGithubTools } from '@github-tools/sdk'
const tools = createGithubTools({
requireApproval: {
createBranch: false,
forkRepository: true,
createRepository: true,
mergePullRequest: true,
createOrUpdateFile: true,
closeIssue: true,
createPullRequest: false,
addPullRequestComment: false,
createIssue: false,
addIssueComment: false,
},
})
Assess risk by operation
| Operation | Risk | Suggested policy |
|---|---|---|
createRepository | High | Always require approval |
forkRepository | High | Always require approval |
createOrUpdateFile | High | Always require approval |
mergePullRequest | High | Always require approval |
closeIssue | Medium | Require in production repos |
updateIssue | Medium | Require in production repos |
createPullRequest | Medium | Optional in trusted CI |
updatePullRequest | Medium | Require in production repos |
createBranch | Low | Usually skip |
deleteBranch | High | Always require approval |
addPullRequestComment | Low | Usually skip |
updatePullRequestComment | Low | Usually skip |
deletePullRequestComment | Medium | Require in production repos |
createPullRequestReview | Medium | Require in production repos |
replyToReviewComment | Low | Usually skip |
resolveReviewThread | Low | Usually skip |
requestReviewers | Low | Usually skip |
addIssueComment | Low | Usually skip |
updateIssueComment | Low | Usually skip |
deleteIssueComment | Medium | Require in production repos |
addLabels | Low | Usually skip |
removeLabel | Low | Usually skip |
createLabel | Medium | Confirm |
updateLabel | Medium | Confirm |
deleteLabel | High | Always confirm |
addAssignees | Low | Usually skip |
removeAssignees | Low | Usually skip |
addIssueReaction | Low | Usually skip |
addCommentReaction | Low | Usually skip |
addDiscussionComment | Low | Usually skip |
markNotificationRead | Low | Usually skip |
deleteGist | High | Always require approval |
createGist | Medium | Optional in trusted CI |
updateGist | Medium | Require in production |
createGistComment | Low | Usually skip |
triggerWorkflow | High | Always require approval |
cancelWorkflowRun | High | Always require approval |
rerunWorkflowRun | Medium | Require in production repos |
createRelease | High | Always require approval |
updateRelease | Medium | Require in production repos |
deleteRelease | High | Always require approval |
Override approval per tool
You can also set needsApproval via the overrides option, which supports all AI SDK tool properties:
createGithubTools({
overrides: {
addIssueComment: { needsApproval: false },
mergePullRequest: { needsApproval: true },
},
})
When both requireApproval and overrides set needsApproval for the same tool, the overrides value wins (it is applied last).
eve approval (richer policies)
On the eve extension (recommended) or the deprecated direct /eve import, requireApproval supports boolean gates, 'once' (approve once per session), string sugar ('always' / 'never'), input-dependent predicates, and passthrough of eve's always() / once() / never() helpers. Write tools default to always() when unlisted.
import githubExtension from '@github-tools/eve-extension'
export default githubExtension({
preset: 'maintainer',
requireApproval: {
mergePullRequest: true,
createIssue: 'once',
createOrUpdateFile: ({ toolInput }) => toolInput?.owner !== 'vercel-labs',
},
})
Unlike createDurableGithubAgent, eve approval pauses the session durably until a person approves.