Releases and migration safety for agents
This reference extends https://app.tokay.io/llms.txt with release and migration safety actions for AI agents. Use these actions only when the user explicitly asks or a named readiness action requires them.
Last updated
AI agent? Start with llms.txt.
The release model
- Tokay rehearses every managed database migration against a disposable clone of the production data before anything touches production. The evidence from that rehearsal, not the SQL text, is what release policy judges.
- Each
deploymentReleaseSessionis one ordered resource plan. Its typedcombinedImpactAssessmentcontains observed facts,releaseAnalysiscontains AI verdicts, andpolicyResult.reasonsexplains any park. Internal rehearsal receipts remain flexible JSON; clients never parse them. releaseSafetyModedecides how much of that authority is automatic.MANUALparks everything, including rollbacks.STRICTapplies only deterministically additive changes automatically.NORMAL, the default, adds changes the AI judged safe.UNRESTRICTEDapplies everything automatically, still snapshotting managed databases first. Deploy calls accept an optionalreleaseSafetyModewhere the strictest value wins, so a request can narrow authority for one deploy but never widen it.- A parked release is not a failure.
deployReadiness.action: CONFIRM_RELEASEmeans evidence is waiting for a human decision. Your job is to read it, summarize it faithfully, and confirm only after the user agrees. - External databases that Tokay does not host get no rehearsal and no snapshot, and park under every mode except
UNRESTRICTED.
What to call
| To | Use |
|---|---|
| Detect a park | deployReadiness { action targetDeployment { id } } |
| Read the evidence | targetDeployment.releaseSessions |
| Apply the parked plan | confirmDeploymentRelease |
| Change the dial | setProjectReleaseSafety / setServiceReleaseSafety |
| Review a proposed migration command | service.releaseActionOverrides, updateServiceReleaseActionOverride |
Read a parked release
When deployReadiness.action is CONFIRM_RELEASE, read deployReadiness.targetDeployment. Do not assume the newest deployment row is the parked one.
query ReleaseConfirmation($serviceId: ID!) {
service(id: $serviceId) {
deployReadiness {
status reason action message
targetDeployment {
id state waitReason releaseSafetyMode releaseStrategy
releaseSessions(first: 100, orderBy: CREATED_AT_ASC) {
nodes {
id isExternalTarget
projectResource { id resourceType runtimeName }
combinedImpactAssessment {
preTrafficChanges { type operation requiresConfirmation database subject }
finalChanges { type operation requiresConfirmation database subject }
tableDeltas { database tableName inserts updates deletes }
durationMs hasUnknownImpact
unknownReasons { code database message }
hasUnverifiedSideEffects
}
releaseAnalysis {
currentCodeSafe currentCodeSafeReasons newCodeSafe newCodeSafeReasons
dataSafety dataSafetyReasons startupMigrationWarning
}
policyResult {
decision
reasons { code message analysisReasons observedSeconds windowSeconds }
}
actions(first: 100, orderBy: ACTION_INDEX_ASC) {
nodes {
commandDisplay evidenceState
releaseExecutions(first: 20, orderBy: CREATED_AT_ASC) {
nodes { type state exitCode logTail }
}
}
}
}
}
}
}
}
}
Summarize policyResult.reasons, destructive finalChanges, and the releaseAnalysis verdicts before confirming. preTrafficChanges is what the new code first sees. finalChanges is the completed plan. dataSafety is SAFE, RISKY, or UNCERTAIN. Reason codes include DATA_SAFETY_RISKY, EXTERNAL_DATABASE_UNVERIFIED, HARD_STOP_EXCEEDS_AUTO_WINDOW, MANUAL_MODE, REAPPLIES_UNDONE_CHANGE (the release changes data again right after a rollback restored it), and TOKAY_AUTHORED_DATA_CHANGE (it rewrites rows in a migration a Tokay fix proposal wrote).
Confirm
mutation Confirm($deployment: ID!) {
confirmDeploymentRelease(input: { deployment: $deployment }) {
deployment { id state }
}
}
The first call changes nothing and fails with CONFIRMATION_REQUIRED, carrying the evidence summary and a token in extensions.confirmation. Repeat it with confirmationToken added to the input once the user agrees. Confirming runs the rehearsed plan against production. Tokay snapshots each managed database immediately before mutating it. After confirming, poll the service back to state: DEPLOYED with deployReadiness.status: UP_TO_DATE. A release that applied automatically shows the same evidence trail afterward, a REHEARSAL row and then a PRODUCTION row per action, so you can always answer what ran and why it was allowed.
The safety dial
releaseSafetyMode lives on the project (project.releaseSafetyMode) and services inherit it. A service can override with its own value, where null means inherit. Direct API clients call setProjectReleaseSafety(input: { project: $id, releaseSafetyMode: MANUAL }) or setServiceReleaseSafety(input: { service: $id, releaseSafetyMode: null }). Loosening the effective mode requires PROJECT_DESTROY and confirms first: the first call fails with CONFIRMATION_REQUIRED and its impact, and the repeated call with confirmationToken applies it. Tightening needs only PROJECT_WRITE and applies at once. Under NORMAL, do not expect every statement that looks destructive to park. The rehearsal runs against real data, and a drop that loses nothing observable can be judged safe and apply on its own. Change the dial only when the user asks for it. If the user wants a guaranteed gate, set MANUAL and treat CONFIRM_RELEASE as the routine path. bypassRunPrediction: true on a deploy call overrides only an AI "new code won't work" prediction. Rehearsal failures always block.
A release that drops or lossily changes schema, or deletes or rewrites existing rows, has policyResult.isDestructive: true, whether it parked or applied on its own. Once it runs, Tokay tells the user: the service's Activity gets a warning naming what changed, and whoever deployed it gets an email. Its restore point's expiresAt says how long it is kept, 7 days from the release.
Migration command overrides
UNCONFIRMED_RELEASE_ACTION as a deploy blocker means Tokay found migration machinery it cannot run automatically and proposed a command. List the service's releaseActionOverrides and review commandArgv, workingDirectory, and timing. Enable with updateServiceReleaseActionOverride(input: { id: $id, patch: { isEnabled: true } }), editing commandArgv in the same patch when the proposal is wrong, or dismiss it with dismissServiceReleaseActionOverride(input: { serviceReleaseActionOverride: $id }). Never enable a command you have not shown the user.
Maintenance holds
deployReadiness.action: ROLL_BACK means a hard-stop release changed the database and then failed, so the service serves its maintenance response. The version before the release may not run on the data as it is now. Roll back to deployReadiness.targetDeployment, which is still the current deployment, with rollbackService and restoreData: true to put the data back as it was before the release. Nothing was written to it while the service was down, though other services using the same database may have written. Or push a fix, which takes the hold over. See the operations reference for rollback.
Error shapes
| You see | It means | Do this |
|---|---|---|
deployReadiness.action: CONFIRM_RELEASE |
Evidence is parked for a decision | Read targetDeployment, summarize, confirm only with user agreement |
waitReason: AWAITING_RELEASE_CONFIRMATION |
Same park, seen from the deployment row | Follow the readiness action, not this field alone |
state: FAILED on a REHEARSAL row |
The migration failed against the clone | Fix the migration and push again. Rehearsal failures never reach production |
policyResult.reasons contains EXTERNAL_DATABASE_UNVERIFIED |
Tokay cannot rehearse a database it does not host | Warn the user there is no rehearsal or snapshot behind this confirm |