Skip to Content
PoliciesRead/Write Governance

Read/Write Governance

Read/write governance lets a project decide which governed agent actions may proceed, which require human review, and which are denied. The control is a project policy over Keel-derived action facts: access level, risk tags, connector identity, classifier source, and registry version.

For governed routes, Keel records those facts on the permit/audit metadata. On supported plans, decision snapshots, signed exports, and Keel’s tamper-evident integrity stack can then show what Keel classified, which policy ran, and what decision Keel returned for the actions that routed through Keel. That is the proof boundary; it is not a claim that Keel governs every action an agent can take off path.

What Keel governs

Keel governs actions that route through a Keel decision boundary:

SurfaceWhat Keel can governBoundary
Model calls through Keel execution routesPolicy and budget before provider dispatchModel operations are usually read on the access ladder, but billable calls can also carry the spend risk tag.
MCP tools routed through KeelExact tool calls after Keel resolves a verified connector identity and tool nameExact mapped names classify as read, write, or admin; unmapped names classify as unknown.
Payments routed through KeelSpend-bearing payment actionsPayment and positive-cost actions carry spend.
Code execution routed through KeelCode-execution operations and known code-exec toolsClassified as admin with code_exec.
Credential-scoped databasesDatabase access through Keel-verified read-only or read-write credentialsThe downstream credential scope is the control; Keel does not parse SQL text to decide read versus write.

Keel does not govern direct calls the agent makes with its own provider, API, browser, database, or tool credentials. Browser and computer-use actions are coarse unless a concrete action is mediated by a governed Keel route or tool. On permit-first integrations, Keel records the decision before execution, but the caller still owns the downstream call and must honor the decision.

What Keel classifies

When action access is enabled for a project, governed policy context can include:

FieldMeaning
context._keel.action_access_levelOne of none, read, write, admin, or unknown.
context._keel.action_risk_tagsIndependent risk tags: spend, egress_external, data_export, and code_exec.
context._keel.action_access_sourceWhere the classification came from, such as keel_curated_connector_map, keel_trusted_credential_scope, operation_intrinsic, or none.
context._keel.action_access_confidenceClassification confidence. A read classification requires high confidence.
context._keel.action_access_map_versionThe classifier registry version used for mapped connector or credential-scope classifications. The current live registry verified for this page is 2026-07-02.1.
context._keel.action_access_registry_hashHash of the active classifier registry manifest.
context._keel.action_access_unknown_reasonWhy Keel could not classify the action, when the level is unknown.
context._keel.connector_identityThe Keel-verified connector identity. Keel does not trust a customer-renamable MCP server slug for read/write gates.
context._keel.intent_mismatchTripwire only: true when the caller declared less access than Keel derived, or Keel could not confirm the declared access.

Caller-supplied context._keel values are stripped before evaluation. A caller can declare intent, but declared intent never grants access.

Access levels

Access level is one ordered ladder. unknown is not a rung; it is the fail-closed sentinel.

LevelMeaningExamples in the live registry
noneNo action access beyond the permit decision itself.Used as an allowable read-only level; most concrete tools classify as read, write, admin, or unknown.
readRetrieves existing state without mutating the downstream system.GitHub get_file_contents; database query through postgres.readonly; Stripe get_payment_intent; filesystem read_text_file; Slack conversations.info.
writeMutates content, resource state, workflow state, or money movement.GitHub create_issue; database query through postgres.readwrite; Stripe create_payment; filesystem write_file; Slack chat.postMessage.
adminChanges privileged control state or runs a high-authority operation.GitHub merge_pull_request or create_repository; Google Drive share_file; S3 PutBucketPolicy; Slack conversations.invite; code execution run_command. The current registry does not expose an admin bucket for credential-scoped database or Stripe tools.
unknownKeel did not classify the action at high confidence.Unmapped MCP tools, unverified connector identities, unscoped database query, and generic common-MCP names such as read, list, get, or search.

Risk tags

Risk tags are independent of access level. A read-only policy should check both the ladder and the tag set.

TagMeaningExamples in the live registry
spendThe action spends, reserves, refunds, transfers, or can incur billable cost.Stripe create_payment, stripe_api_write, create_refund; payment action payment.execute; model calls with positive estimated cost.
egress_externalThe action sends data outside the expected trust boundary.Slack chat.postMessage; GitHub write/admin tools such as create_issue; Google Drive share_file; Stripe send_stripe_mcp_feedback.
data_exportThe action exports or exposes data as an explicit export/share/report operation.Google Drive share_file; S3 bucket-policy/public-access admin tools; Stripe stripe_report.
code_execThe action executes code.Operation code_execution; code-execution tools such as run_command, bash, python, and node.

Fail-closed behavior

Read/write governance is intentionally conservative:

  • unmapped or unknown tools classify as unknown
  • unknown is not read-only safe and should review or deny
  • policy authoring rejects active policies that allow unclassified actions
  • low- or medium-confidence classifications do not become read
  • generic MCP verb names such as read, list, get, or search are not trusted as read semantics by themselves
  • database read/write classification comes from the credential scope Keel provisioned or verified, not from SQL parsing
  • any risk tag, including a future tag, blocks read-only-safe classification

The default for unknown and unmapped tools is review. Projects can write stricter policies that deny them instead.

Enable read-only mode for a project

For eligible hosted projects, read/write controls are generally available. They do not change behavior until the project has an active policy that uses context._keel.action_access_* fields.

In the dashboard, create or edit a project policy in Guided or Technical mode. Choose the read-only access mode, or author an equivalent policy. Save it as the active project policy.

Read-only means:

  • allow action_access_level values none and read
  • review or deny write, admin, and unknown
  • review or deny any non-empty action_risk_tags list

A read-only review policy has this shape:

{ "name": "Read-only guardrail", "rules": [ { "if": { "any": [ { "field": "context._keel.action_access_level", "op": "in", "value": ["write", "admin", "unknown"] }, { "field": "context._keel.action_risk_tags", "op": "len_gt", "value": 0 } ] }, "action": "require_human_review" } ] }

Use deny instead of require_human_review when the project should block matching actions outright.

If read/write fields are not enabled for a project, Keel rejects active policies that reference them. A policy that can match unknown cannot use allow; for a read-only policy, use require_human_review or deny.

Coverage boundaries

Keel’s strongest read/write coverage is on surfaces where Keel is on the execution path or verifies the downstream credential scope.

SurfaceBoundary
GitHubDeepest connector-map coverage today. Registry 2026-07-02.1 maps audited GitHub MCP tool names exactly; future or absent names remain unknown.
DatabaseCredential-scoped, not SQL-parsed. postgres.readonly/database.readonly classify as read; postgres.readwrite/database.readwrite classify as write; unscoped database identities are unknown.
Stripe and paymentsRetrieve/list tools classify as read; create/update/payment/refund/transfer tools classify as write and usually carry spend; mixed export/report tools are not treated as read.
Files and storageFilesystem, Google Drive, and S3 use exact-name maps. Generic file-like names under the wrong connector are intentionally unmapped.
Slack, Gmail, emailSlack and Gmail have exact-name read/write/admin coverage. Generic email has no read-classified tools until a connector-specific contract pins exact non-mutating semantics.
Common MCPGeneric names alone do not prove semantics. read, list, get, and search are unknown, not read.
Browser or computer-useCoarse. computer.use is ambiguous from the operation alone and rounds up; off-path browser activity is not governed.

Registry coverage is versioned and audited. The policy-authoring catalog reports project MCP coverage from the project’s configured tool allowlists, including the number of unknown tools. Missing entries are safer than wrong read entries: an unmapped tool reviews by default, while a mutating tool misclassified as read could fail open.

Last updated on Edit this page on GitHub