GitHub Action that starts a LatchGate execution security gate for AI agent CI pipelines.
Every tool call your agent makes during the workflow is authenticated, policy-evaluated, sandboxed in WASM, and produces a signed audit receipt.
name: Agent CI
on: push
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Start LatchGate
id: latchgate
uses: latchgate-ai/latchgate-action@v1
- name: Run agent
run: python my_agent.py
env:
LATCHGATE_URL: ${{ steps.latchgate.outputs.url }}The action starts LatchGate + Redis + OPA via Docker Compose, waits for health, and exports LATCHGATE_URL for subsequent steps. On completion, the audit ledger is uploaded as a workflow artifact.
| Input | Default | Description |
|---|---|---|
version |
latest |
LatchGate image tag (0.1.0, latest) |
port |
3000 |
Host port to expose the gate on |
upload_ledger |
true |
Upload audit ledger as workflow artifact |
ledger_artifact_name |
latchgate-audit-ledger |
Artifact name for the ledger |
| Output | Description |
|---|---|
url |
Gate base URL (e.g. http://localhost:3000) |
compose_file |
Path to the generated docker-compose file |
LATCHGATE_URL is also set as an environment variable for all subsequent steps.
- uses: latchgate-ai/latchgate-action@v1
id: latchgate
- run: pip install latchgate
- run: |
python -c "
import asyncio
from latchgate import LatchGateClient
async def main():
async with LatchGateClient(agent_id='ci') as c:
r = await c.execute('http_fetch', {'url': 'https://httpbin.org/get'})
print(f'receipt: {r.receipt_id}')
asyncio.run(main())
"- uses: latchgate-ai/latchgate-action@v1
with:
version: "0.1.0"- uses: latchgate-ai/latchgate-action@v1
with:
port: "8080"The runner VM is destroyed after the job, removing all state. For workflows that need ports or resources freed mid-job:
- uses: latchgate-ai/latchgate-action@v1
id: latchgate
- run: python my_agent.py
- name: Stop LatchGate
if: always()
run: docker compose -f ${{ steps.latchgate.outputs.compose_file }} down -vThe audit ledger is uploaded as a workflow artifact by default. Download it from the Actions tab to inspect every decision:
sqlite3 audit.db "SELECT action_id, decision, trace_id FROM events ORDER BY created_at DESC LIMIT 10"The action starts three containers via Docker Compose:
| Service | Image | Purpose |
|---|---|---|
latchgate |
ghcr.io/latchgate-ai/latchgate:{version} |
Gate server, WASM providers |
redis |
redis:7-alpine (digest-pinned) |
Replay cache, budget tracking |
opa |
openpolicyagent/opa:1.16.1 (digest-pinned) |
Rego policy engine |
Redis and OPA images are pinned by @sha256: digest to prevent supply-chain attacks. The digests are updated alongside the main LatchGate release.
- The gate runs in
LATCHGATE_DEV_MODE=true(ephemeral keys, TCP transport). This is appropriate for CI — not production. - All containers run with
read_only: truewhere possible. - Dependency images are digest-pinned — tag-only pulls are not used.
- The audit ledger captures every decision with hash-chain integrity.
- The runner VM is destroyed after the job, removing all state.
Apache-2.0. See LICENSE.