Gatemole
Formerly called Vouch.
Gatemole is an enforcement kernel and transaction Runtime for autonomous agents. Agents may propose work, but Gatemole controls the boundary between that proposal and an exact effect.
Gatemole does not replace an agent framework, model provider, identity provider, container runtime, Kubernetes or the host operating system. It controls the authority and transaction boundary around agent work.
One kernel serves two product experiences:
- Gatemole Developer Runtime is the local experience for developers who want to run an existing coding agent in an isolated Git transaction, inspect its exact effects and control release. A low-level, manually operated local-Git integration exists today; the self-serve developer preview is still a milestone.
- Gatemole Agent OS is the target enterprise experience: the same
gatemoledkernel plus non-bypassable action connectors, cross-run policy and a Control Plane for a fleet of Runtimes. Those fleet and remote-system capabilities are planned, not implemented.
These are not separate engines. Developer adoption exercises the same kernel semantics that future enterprise deployments require.
What would a team use Gatemole for?
Use Gatemole when a software agent needs permission to change a repository, but should not also receive permission to approve or publish its own work. Gatemole is the control layer around an existing agent; it is not the agent that diagnoses or writes the fix.
Consider a real payments incident, PAY-1842: valid customers are being logged
out because the API rejects their refresh tokens. The on-call engineer wants a
coding agent to inspect the service, fix the authentication code, add a
regression test and use a model while it works.
The pain: the worker is also inside the control boundary
A common direct-agent setup looks roughly like this (the command varies by agent):
cd /srv/repos/payments-api
export MODEL_PROVIDER_API_KEY="$REAL_PROVIDER_KEY"
export GIT_RELEASE_TOKEN="$PAYMENTS_GIT_TOKEN"
payments-coder --task-file tickets/PAY-1842.md
The agent may produce a perfectly good fix. The operational problem is that the team has also placed the live checkout, inherited credentials, network and the account's Git authority inside the same process boundary as the worker. Its transcript is useful context, but it is not an independent authority log. If the process edits an unrelated file, runs the wrong test, crashes halfway or pushes a branch, the surrounding workflow has to discover and recover from that after the fact.
Some agent products already provide their own sandbox, permission prompts or review UI. Gatemole does not claim those features are absent everywhere. Its specific offer is an agent-independent enforcement boundary owned by a separate local daemon:
| Control | Direct agent invocation | Same agent through Gatemole |
|---|---|---|
| Task | Prompt and runner state | Content-bound, durable admission tied to one run and transaction |
| Workspace | Live checkout or the agent product's sandbox | Daemon-created private Git worktree; source checkout is not mounted |
| Model access | Provider credential and network policy of the agent process | Short-lived broker token; provider credential remains in gatemoled; no model network unless admitted |
| What changed | Agent transcript and a Git diff inspected afterward | Daemon-authored normalized effects plus hash-chained execution and transaction receipts |
| Testing | Often requested and run by the same worker | Separately pinned verifier runs against the exact frozen tree |
| Approval | External convention or product-specific review | Signed decision bound to the immutable approval package |
| Release | Whatever Git authority the process or account has | Distinct release identity and compare-and-swap to an allowed local ref |
| Crash/retry | Runner-specific; partial state may need manual interpretation | Same admission resumes the transaction; earlier execution receipts remain immutable |
payments-coder in both columns is the team's real agent or adapter—not a
Gatemole-provided fake agent. The point of the comparison is to keep the worker
constant and move authority out of it.
With Gatemole, the team instead uses this workflow:
- The operator admits the exact ticket to a named, digest-pinned agent.
gatemoledgives the agent a private Git worktree and, if authorized, a transaction-scoped model-broker token. It does not give the agent the source checkout, provider credential, daemon socket or release credential. - Gatemole freezes and inventories the resulting Git effects. The operator can see that the agent changed, for example, the refresh-token implementation and its test—not merely read the agent's description of what it changed.
- A separately configured verifier runs the authentication tests against the exact frozen tree.
- A security reviewer signs the immutable approval package. The coding agent cannot approve itself, and a later change invalidates that approval.
- A different release identity publishes the approved commit to a pre-existing allowed local Git ref with compare-and-swap protection.
After the Runtime has been configured with the payments-coder agent, model
broker, verifier, OIDC identities, approval trust and allowed release ref, the
day-to-day operator flow is:
export GATEMOLE_IDENTITY_TOKEN="$PAYMENTS_OPERATOR_TOKEN"
gatemole --repo /srv/repos/payments-api run \
--socket /run/gatemole/gatemoled.sock \
--namespace payments \
--id tx:pay-1842 \
--run run:pay-1842 \
--require-enforcement-profile production \
--intent-file tickets/PAY-1842.md \
--agent payments-coder \
--model-provider openai
gatemole --repo /srv/repos/payments-api review tx:pay-1842 \
--socket /run/gatemole/gatemoled.sock \
--namespace payments
The operator then asks an independently pinned verifier to test the frozen candidate and prepares the exact local ref update:
VERIFIER_IMAGE="$(cat /etc/gatemole/images/go-verifier.ref)"
gatemole --repo /srv/repos/payments-api tx verify \
--socket /run/gatemole/gatemoled.sock \
--namespace payments \
--id tx:pay-1842 \
--name auth-tests \
--image "$VERIFIER_IMAGE" \
-- /usr/local/bin/run-auth-tests
gatemole --repo /srv/repos/payments-api tx prepare \
--socket /run/gatemole/gatemoled.sock \
--namespace payments \
--id tx:pay-1842 \
--git-ref refs/heads/agent-release/pay-1842
The reviewer and releaser use their own short-lived identities:
export GATEMOLE_IDENTITY_TOKEN="$PAYMENTS_REVIEWER_TOKEN"
gatemole --repo /srv/repos/payments-api approve tx:pay-1842 \
--socket /run/gatemole/gatemoled.sock \
--namespace payments \
--key /secure/payments-reviewer.key \
--key-id key:payments-reviewer \
--approver human:alice \
--issuer https://login.acme.example/ \
--class security-reviewer
export GATEMOLE_IDENTITY_TOKEN="$PAYMENTS_RELEASER_TOKEN"
gatemole --repo /srv/repos/payments-api apply tx:pay-1842 \
--socket /run/gatemole/gatemoled.sock \
--namespace payments \
--actor operator:payments-release \
--actor-kind operator
If the agent or daemon fails, repeating the identical gatemole run resumes
the same admitted transaction and retains the earlier execution receipts. It
does not silently turn a failed attempt into releasable work.
This is the useful boundary implemented today: governed agent work in a local Git repository. Release updates only the configured local ref; Gatemole does not yet push or merge a pull request, deploy the service, mutate a database or control Kubernetes. Those remote effects require the planned connector and Control Plane layers. The complete setup assumptions and operator walkthrough are in Runtime examples.
Architecture: where the OS, Runtime and kernel sit
Gatemole Agent OS names the complete target system; it is not another process
or deployment. The enforcement function lives in one or more customer-side
Gatemole Runtime installations. Each Runtime contains a trusted gatemoled
kernel. The planned Gatemole Control Plane manages a fleet of Runtimes.
Gatemole Agent OS (the complete product)
|
|-- Gatemole Control Plane [planned]
| fleet policy | approvals | audit | incident response
| |
| signed authority
| v
|
`-- Gatemole Runtime [customer-side enforcement boundary]
|
|<-- agent task
|
|-- gatemoled kernel
| admission | live authority | budgets | Git journal
| effect inventory | sequence policy | approval
| local-ref commit [current]
| action broker | cross-run policy | reconciliation
| [planned]
|
|-- agent sandbox + adapter --> private Git worktree
| [current]
|
`-- connector drivers [planned]
|
v
GitHub | Kubernetes | PostgreSQL | SAP | cloud
Administrators and approvers operate the Control Plane; Runtime receipts flow
back to it for audit and incident response.
The operating-system analogy is precise:
| Name | Meaning | Status |
|---|---|---|
| Gatemole Developer Runtime | The local product experience around one Runtime: package an agent, execute it in an isolated Git transaction, inspect exact effects and control release. | Low-level integration, Runtime profile initialization, diagnostics and exact review/apply/reject shell implemented; packaged adapters, watch and live cancellation planned |
| Gatemole Agent OS | The enterprise product experience and complete target architecture: Control Plane, Runtime fleet, transaction protocol and connector model. It is an umbrella, not a process. | Product direction |
| Gatemole Control Plane | Organization-wide fleet, policy, approval, audit and incident management. It manages Runtimes but does not execute agent actions. | Planned |
| Gatemole Runtime | The deployable enforcement boundary installed in a customer environment. It contains gatemoled, agent sandboxes, local durable state and connector drivers. |
Runtime identity, a narrow single-node local-Git profile and exact profile-bound admission are implemented |
gatemoled kernel |
The trusted daemon that owns admission, authoritative lifecycle state, budgets, policy decisions, the transaction journal, approvals and commit coordination. | Runtime preflight, atomic task admission, live OCI authority revalidation, paired execution settlement/recovery and supported budget charging implemented; supervision and action enforcement are still converging |
| Agent sandbox | The isolated, untrusted environment in which an agent loop executes. It receives no downstream production credentials. | OCI implementation available |
| Agent adapter | Connects an existing agent framework or command to the kernel. It may request work and actions but cannot authorize itself or create receipts. | Command/profile and lower-level integration exist; supported broker API planned |
| Connector driver | Performs typed operations against one downstream system after kernel authorization and reconciles external state. gatemoled records authoritative receipts and coordinates recovery. |
Generic interface and remote drivers planned. Local Git currently uses a dedicated transaction path, not that future interface |
| Gatemole Contracts | Optional verification module that turns human-owned intent into evidence obligations used by Runtime policy. | Beta |
The diagram states the intended ownership boundary, not a completion claim.
Today gatemole run first asks the selected daemon to match the repository's
Runtime identity, report the requested enforcement profile and inspect the
selected digest-pinned image. This preflight happens before
task authority or a worktree is created. Task admission then durably binds the
exact Runtime ID and daemon enforcement profile with the content-bound
contract, real run, initial grants and transaction. Before OCI launch,
gatemoled reloads that live authority and fail-closed derives the permitted
image, command, full-workspace access, model-broker access and deadline. It
then atomically verifies the admitted run and transaction heads while recording
execution start in both ledgers, before starting any broker or agent workload.
Settlement atomically closes the same execution in both ledgers, clears the
run's active-execution binding and durably charges elapsed wall time plus
verified model-call and token usage against the remaining hard limits. The raw
transaction receipt retains the execution timestamps and counters if a charge
saturates. Daemon restart performs the same paired settlement for an
interrupted workload and marks unfinished model calls unknown before charging
them. Live cancellation, tool/cost accounting and the mediated connector action
path remain later Runtime milestones.
The target remote-effect path is:
agent proposes an action
-> gatemoled authenticates the run and delegated authority
-> gatemoled evaluates the action and complete transaction sequence
-> deny | request approval | authorize
-> connector driver stages or executes with scoped credentials
-> gatemoled records the receipt and verifies the outcome
-> commit | compensate | reconcile | require manual recovery
This broker-and-connector path is not implemented in the current production profile; the older action endpoints are disabled there. Today the contained effect boundary is mutation of a private Git worktree followed by exact inspection, verification, approval and a local-ref compare-and-swap.
An agent with direct downstream credentials can bypass Gatemole. A future multi-system deployment is therefore enforcement-grade only when production credentials and network paths are available exclusively through Gatemole connector drivers.
The current local-Git transaction is the first kernel transaction-and-effect slice. A complete Gatemole Agent OS external claim requires both non-bypassable, multi-system Runtime enforcement and a Gatemole Control Plane managing a fleet of those Runtimes.
Developer Runtime: current local-Git integration
The current runtime requires Git, an OCI engine such as Docker, a running
gatemoled, and a digest-pinned agent image.
This is a low-level developer integration, not yet a self-serve desktop agent
environment. gatemole runtime init creates a strict repository-owned profile
and a local Runtime identity. gatemole doctor diagnoses Git, OCI, profile,
local-image and daemon readiness. gatemole review shows the daemon-bound
status, exact effects, evidence IDs and frozen patch; diff, apply and
reject expose the corresponding task-oriented operations. Packaged adapters,
daemon supervision, watch and live cancellation remain roadmap work.
Build the CLI from source:
go install ./cmd/gatemole
gatemole version
gatemole --help
In a Git repository with a HEAD commit, register an agent image that is
already present in the local OCI engine:
gatemole --repo /path/to/service runtime init \
--agent coding-agent \
--image registry.example/coding-agent@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef \
--source-digest sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb \
-- /usr/local/bin/agent
--source-digest identifies the source or build input used for that image; it
is deliberately not invented by Gatemole. Initialization also creates
.gatemole/runtime.json, a random local Runtime instance identity, and rules that
keep it, SQLite/WAL files, locks and the daemon socket out of Git. Commit
.gatemole/agent-profiles.json and .gatemole/.gitignore; do not commit
.gatemole/runtime.json.
This is a hard pre-1.0 state cutover. If a repository still contains .vouch,
Gatemole fails before writing any new state; it never merges, renames, or
rehashes old configuration, ledgers, evidence, or signatures automatically.
Archive or remove the legacy directory deliberately, then initialize
.gatemole.
Start the repository-local development daemon in one terminal:
gatemole --repo /path/to/service daemon
By default, transaction worktrees live in a canonical, repository-scoped
directory beneath the current user's validated runtime or cache directory,
not in a shared predictable /tmp/gatemole-transactions path. A custom
--transaction-root is validated before the ledger opens.
In another terminal, diagnose the selected integration and run it:
gatemole --repo /path/to/service doctor --agent coding-agent
gatemole --repo /path/to/service run \
--intent "Fix authentication without changing public behavior" \
--agent coding-agent
Doctor warnings, such as an intentionally stopped daemon or omitting
--agent, do not make the command fail. A selected missing image, invalid
profile, unavailable OCI engine or unready existing daemon does.
When the socket exists, doctor uses the daemon's authoritative Runtime
preflight instead of treating a separate CLI-side OCI probe as proof.
For a developer, the integration contract is deliberately small:
- Package the existing agent as a digest-pinned OCI image.
- Make its command read the retained task at
$GATEMOLE_TASK_PATH. - Let it edit only
/workspaceand return a normal process exit code. - Start it with
gatemole run; do not give the container the daemon socket, repository credentials or downstream production credentials. - Inspect the transaction and its hash-chained events before verification, approval and release.
For example, an agent entrypoint can begin with:
#!/bin/sh
set -eu
test "$GATEMOLE_RUNTIME_ROLE" = agent
test -r "$GATEMOLE_TASK_PATH"
cd /workspace
# Invoke your existing agent loop here. All intended file effects stay in this
# detached transaction worktree.
exec /opt/my-agent --task-file "$GATEMOLE_TASK_PATH"
gatemole runtime init writes the strict, repository-owned
.gatemole/agent-profiles.json and local-only .gatemole/runtime.json. Select the
agent profile by name:
gatemole --repo /path/to/service run \
--intent "Fix authentication without changing public behavior" \
--agent coding-agent
The public profile schema is
schemas/gatemole.agent_profiles.v0.schema.json,
with a complete
example profile. Gatemole
binds the selected profile, final command, pinned image and exact task intent
into a durable task envelope. For OCI execution, gatemole run first preflights
the exact local Runtime ID, enforcement profile and image with gatemoled; a
failure creates neither task authority nor a worktree. Admission v1 then binds
that Runtime ID and the daemon's actual enforcement profile into the durable
transaction. Daemon-owned OCI agents receive the task envelope read-only at
/gatemole/task.json.
The product CLI loads .gatemole/runtime.json and binds every daemon call from
the run, transaction, low-level kernel and action surfaces to that ID.
Preflight and current task admission carry the expected ID in their validated
bodies; lifecycle mutations, reads and long-running agent/verifier operations
also carry Gatemole-Runtime-ID. A configured daemon rejects a missing or
different header before those handlers run. This is exact Runtime correlation,
not a secret or an authentication credential.
Model egress is absent unless the task explicitly requests the configured
daemon broker, for example with --model-provider openai. The provider
credential never enters the agent container:
# No model authority: network=none and no model credential in the container.
gatemole --repo /path/to/service run \
--intent "Apply the deterministic migration" \
--agent migration-agent
# Explicit model authority: only the configured OpenAI-compatible broker is
# reachable. OPENAI_API_KEY is a transaction-scoped broker token, not the
# provider credential.
gatemole --repo /path/to/service run \
--intent "Fix the failing authentication test" \
--agent coding-agent \
--model-provider openai
At launch, the kernel derives the run identity, image, command, workspace access, broker access and deadline from live admitted state. A stale run, an expired grant, a changed image or command, a narrower unsupported workspace grant, or an ungranted model provider fails before any broker or agent container starts.
For the complete PAY-1842 operator workflow and the assumptions behind it, see Runtime examples. That guide separately labels its runnable deterministic fixtures as acceptance proofs rather than presenting them as the normal user experience.
gatemole run then creates the isolated worktree, runs the agent, freezes its Git
effects, and performs deterministic sequence validation. Inspect the result
with:
gatemole --repo /path/to/service review <transaction-id> \
--namespace local
# Print only the exact frozen patch (safe to pipe to another tool):
gatemole --repo /path/to/service diff <transaction-id> \
--namespace local
# Advanced lifecycle/debugging surface:
gatemole --repo /path/to/service status <transaction-id> \
--namespace local
gatemole --repo /path/to/service tx effects \
--namespace local --id <transaction-id>
gatemole --repo /path/to/service tx events \
--namespace local --id <transaction-id>
The daemon re-inspects the staged tree before returning a diff. The client
checks its patch digest and transaction/attempt/event binding; a worktree
change after staging fails closed instead of showing a mutable approximation.
After verification, preparation and any required signed approval, gatemole apply <transaction-id> invokes the same release operation as gatemole release. gatemole reject <transaction-id> aborts and discards an unreleased
worktree; it is not live workload cancellation.
Optional local proof: crash and resume the PAY-1842 agent
This is an executable acceptance fixture, not the operator interface described
above. Run it from a Gatemole source checkout to exercise the failure/recovery
invariant without supplying a real agent, repository or production trust
configuration. It requires Git, Go, Docker and jq; Docker may fetch
golang:1.26-alpine the first time:
scripts/gatemolepairedexecutiondemo.sh
The fixture builds a disposable payments API and deterministic agent. Its first
attempt saves the candidate fix in the private transaction worktree and exits
with code 42; after a daemon restart, the second attempt resumes that patch and
runs go test ./internal/auth successfully.
The final JSON report includes both immutable execution receipts, all four
paired run.execution_started/run.execution_finished events, cumulative wall
time across both attempts, a waiting_for_event run with no active execution,
and proof that the developer's source checkout was never modified. See
Runtime examples
for the expected output and equivalent inspection commands.
Production verification and preparation use the advanced tx verify and
tx prepare operations. Reviewers and releasers use the top-level gatemole review, gatemole approve and gatemole apply commands under the hardened
daemon configuration. See Production Runtime Operations
for the complete deployment contract; do not infer production safety from the
development example above.
Production callers should make the expected profile explicit:
gatemole --repo /srv/gatemole/repository run \
--socket /run/gatemole/gatemoled.sock \
--namespace engineering \
--require-enforcement-profile production \
--intent "Fix the approved authentication regression" \
--agent coding-agent
A development daemon cannot satisfy that command, so it fails during preflight before admission or worktree creation.
What the runtime enforces today
The implemented runtime includes:
- Daemon-owned OCI agent and verifier execution.
- Detached, task-scoped Git worktrees.
- Immutable Git-tree staging and exact read-only verifier materialization.
- A normalized, ordered effect ledger and deterministic sequence policy.
- Hash-chained transaction events and crash-recoverable SQLite projections.
- Digest-pinned agent, verifier and model-broker images.
- Policy-controlled model access without exposing the provider credential to the agent.
- OIDC operator identity, signed approval packages and separation of approver and releaser.
- A repository-local Runtime identity, stable Runtime and ledger locks, same-UID Unix peer authentication, daemon-authoritative preflight, and Runtime/profile-bound v1 admission.
- A private, owner-validated transaction staging root and immutable startup snapshots for trust, verifier and model-broker policy inputs.
- Atomic compare-and-swap publication to an allowed local Git ref.
- Bounded Git inspection, workload concurrency, output capture and readiness checks.
Supported deployment profile
The current supported profile is deliberately narrow:
- One node and one security tenant.
- A dedicated trusted host or VM and non-root daemon account.
- One repository and SQLite ledger per runtime boundary.
- One local Runtime identity bound to that ledger and enforcement profile.
- Preloaded, digest-pinned OCI images.
- Required verifier profiles and logically independent signed approval.
- Publication to an allowed local Git ref only.
It does not push to a remote, create or merge pull requests, deploy software, coordinate database or Kubernetes effects, provide multi-tenant isolation, expose a remote control API, or provide high availability. Stable versioned release packaging is also still pending. The exact host, storage, identity, quota and acceptance requirements are documented in docs/PRODUCTION.md.
The Runtime identity, repository-local .gatemole/runtime.lock, and ledger lock
prevent an accidental same-host, same-UID daemon or ledger mix-up even when
environment or database paths differ. They are not fleet enrollment,
cryptographic same-UID daemon attestation or cross-host attestation. Use a
dedicated OS account for a hardened Runtime. Deliberately copying all ignored
identity and ledger state to another repository copies the trust target too.
Organization enrollment, attested Runtime identity and fleet revocation belong
to the planned Control Plane.
Every CLI process that connects to the hardened Unix socket must use that daemon account's effective UID. OIDC tokens still distinguish operators, reviewers and releasers, but the current approval CLI has no separate offline sign-and-submit path; see the production guide before claiming OS-level reviewer-key custody separation.
Gatemole Contracts
Repositories that need semantic release obligations can opt into the Contracts module:
gatemole --repo /path/to/service contracts try --write
gatemole --repo /path/to/service contracts compile
pytest --junitxml .gatemole/artifacts/pytest.xml
gatemole --repo /path/to/service contracts evidence import junit \
.gatemole/artifacts/pytest.xml
gatemole --repo /path/to/service contracts gate
Contracts turn human-owned intent into stable obligation IDs and determine whether supplied evidence covers those obligations. They do not prove arbitrary code correct and are not a generic AI code reviewer.
Documentation
- Real-life Runtime examples
- Agent transactions
- Production runtime operations
- Kernel internals
- Runtime and product roadmap
- Product validation and competitive assessment
- Transaction-control decision
- Durable-supervisor decision
- Threat model
- Gatemole Contracts
- Benchmarks and acceptance
- Contributing
Published documentation: https://duriantaco.github.io/gatemole/
Validation
The repository maintains separate acceptance paths for the Contracts module, kernel semantics, transactions, runtime execution and the supported production profile:
go test ./...
go vet ./...
go run golang.org/x/vuln/cmd/[email protected] ./...
go test -race -count=1 ./internal/kernel/...
scripts/gatemolebench.sh
scripts/gatemolekernelbench.sh --out /tmp/gatemolekernelbench
scripts/gatemoletransactionbench.sh
scripts/gatemoleruntimebench.sh
image="$(scripts/gatemoleproductionfixture.sh --tag gatemole-production-fixture:acceptance)"
GATEMOLE_PRODUCTION_IMAGE="$image" scripts/gatemoleproductionbench.sh
Passing these gates establishes the documented invariants for that revision. It does not establish correctness for arbitrary agent output or expand the supported deployment boundary.
License
Apache-2.0. See LICENSE.