Skip to content
browse the docs

Migration Guide

vanzik v2.0updated view on github

This document tells operators what to expect when upgrading between Vanzik releases. Every release that changes on-disk state, default behavior, or a contract operators may depend on gets a section here.

Upgrading from AgentGuard 1.x? Before 2.0 this project was called AgentGuard. Read v1.x to v2.0: it explains what the 2.0 installers move for you, including the coding-agent hooks that still run the agentguard program. The sections before it describe releases made under the AgentGuard name and use the names of their time.

For a single-line summary of each change, see CHANGELOG.md. For deep-dive release notes, see docs/releases/. For the format-version contract, see docs/FILE_FORMATS.md.


v0.4.0 → v0.4.1#

(Corrected in v1.1.1: v0.4.1 was never tagged or published — no Go module version or PyPI release exists. Its changes first shipped in v0.5.0, so these steps apply when you upgrade from v0.4.0 to v0.5.0 or later.)

What happens automatically#

On first start of a v0.4.1 binary against an audit file written by v0.4.0:

  1. The v040_to_v041 migration detects a headerless v1 audit file.
  2. It writes a byte-for-byte backup to <audit-log>.v040-backup (mode 0600).
  3. It rewrites the live file in place with a schema_version: 2 header record as the first line.
  4. It verifies that the rewritten file parses cleanly and contains the same number of records as the backup.
  5. Startup continues.

If any step fails, the server refuses to start, leaves the original file untouched, and prints a recovery path. No partial migration state is left behind.

What you should do#

Nothing is required. The migration runs on boot. But if you want to preview it:

agentguard migrate --dry-run --audit-log /var/lib/agentguard/audit.jsonl

This logs the intended actions without touching disk. Use this to confirm that the detected file matches what you expect.

Rollback to v0.4.0#

Steps:

  1. Stop the v0.4.1 server.
  2. cp <audit-log>.v040-backup <audit-log> — the backup is exactly the file v0.4.0 wrote.
  3. Replace the binary with v0.4.0.
  4. Start.

v0.4.0 does not understand the schema-2 header and will refuse to read a migrated file; that is what the backup is for. If you deleted the backup deliberately, downgrade is not supported.

The backup is kept. The removal planned for v0.4.3 never shipped: the v040_to_v041 migration and its .v040-backup are still in 2.0 (vanzik migrate --list shows it), and no release deletes the backup. To keep the downgrade path safe from disk cleanup, copy .v040-backup off the server.

Behavioral changes worth knowing about#

  • Audit replay is checkpointed. First start takes as long as it used to (one full replay). Subsequent starts are near-instant — the server resumes from <audit-log>.replay-checkpoint.
  • Audit rotation primitives ship in pkg/audit but are not wired by default in v0.4.1. Continue to rotate audit.jsonl externally on this release. Rotation will be wired by default in v0.5; the rotator gzips rotated files and carries a _meta.rotated_from pointer so startup replay follows the chain.
  • ApprovalQueue eviction is LRU, not bulk-drop. Under extreme load with no resolved entries and a full queue, new approvals return 503 with Retry-After. The previous behavior was silent state loss. If you scrape agentguard_approvals_evicted_total{reason} you will see the events.
  • Session store rejects new logins at the cap instead of silently evicting the oldest session. If you routinely run with more than ~1000 concurrent dashboard sessions you will see 503 on new logins; sign out idle tabs to free slots.
  • /v1/audit?limit= is honored for the first time. The dashboard's existing ?limit=200 query now returns up to 200 entries (clamped to the new proxy.audit.max_limit, default 1000). Scripts that relied on the hard-coded 100 will see up to the requested value.

Deprecation warnings you may see on first load#

  • WARN deprecation feature=policy.time_window_without_require_prior ... — fix by pairing time_window with require_prior in the policy rule, or remove time_window entirely. v0.5.0 will reject the policy at load.

Check /metrics for agentguard_deprecations_used_total before upgrading to v0.5.0.

Forcing a full replay#

The server never refuses to start because of the checkpoint: a missing, corrupt, or stale one triggers a full replay automatically. To force one explicitly (for example after restoring an audit file from backup):

agentguard migrate --reset-checkpoint --audit-log <path>

This deletes <path>.replay-checkpoint — the file agentguard serve reads — and prints checkpoint removed or no checkpoint found. The next server start performs a full replay (as with v0.4.0) and writes a fresh checkpoint.


v0.4.1 → v0.5.0#

What happens automatically#

  • The audit-log binary format is unchanged from v0.4.1 (schema_version: 2). No file rewrite runs.
  • New audit entries written by v0.5+ binaries carry an additional top-level transport field ("sdk", "mcp_gateway", or "llm_api_proxy"). The field is purely additive — existing readers ignore unknown top-level keys, so the schema version does not bump.
  • runServe constructs the rotating logger by default (--audit-max-size-mb 100, --audit-max-backups 5, --audit-max-age-days 30, --audit-compress true). On first restart after upgrade, the live audit.jsonl keeps appending; once it crosses the size threshold, the rotator kicks in and rotated files start to appear as audit.jsonl.YYYYMMDDTHHMMSSZ.gz (or audit.jsonl.YYYYMMDDTHHMMSSZ with --audit-compress=false) alongside the active file.

What you should do#

  1. Audit the audit log rotation chain. If you currently run logrotate (or any other external rotator) against audit.jsonl, do one of:

    • Recommended: disable your external rotator. AgentGuard's built-in rotator handles size, age, and retention via flags.
    • Or keep logrotate and pass --audit-max-size-mb 0 to disable AgentGuard's rotator. Use copytruncate in your logrotate config (see OPERATIONS.md).

    Do not run both at once — the dual-rotator chain corrupts the _meta.rotated_from continuity and breaks startup replay's chain walk.

  2. Sweep your policy YAML for time_window without require_prior. v0.5.0 promotes this from a WARNING to a load error. Find any rule with conditions.time_window and no sibling conditions.require_prior and either pair them up or drop time_window from the rule. v0.4.1's agentguard_deprecations_used_total{feature="policy.time_window_without_require_prior"} counter tells you whether your runtime hit the warning. If the counter is zero and your policy parses cleanly under v0.4.1, v0.5 will load it cleanly too.

  3. Decide on the new policy options:

    • mcp_tool scope — if you use the MCP Gateway, write at least one rule for scope: mcp_tool (configs/default.yaml ships an example; see POLICY_REFERENCE.md). The gateway dual-checks mcp_tool AND the mapped concrete scope (e.g., shell or network), so omitting mcp_tool rules causes default-deny on every tool call.
    • tool_scope_map — operator override surface for the gateway and LLM proxy's tool→scope mapping. Optional; the bundled defaults work for most setups. Add overrides for tools your policy needs to gate at a different scope than the default.
    • unmapped sentinel — if you run the LLM API Proxy, decide your default-deny posture: write a scope: unmapped rule (deny or require-approval) for tool calls the proxy can't classify. The proxy returns synthetic refusal on unmapped denials.
  4. Deploy the new binaries (optional but the headline feature):

    • go install github.com/Caua-ferraz/AgentGuard/cmd/agentguard-mcp-gateway@v0.5.0
    • go install github.com/Caua-ferraz/AgentGuard/cmd/agentguard-llm-proxy@v0.5.0

    Both share the central server's policy file (mount the same policy.yaml into all three processes; each one hot-reloads it when it changes).

  5. Update Python SDK installs to Python 3.9+. v0.5 drops 3.8 (upstream EOL October 2024). The pyproject.toml floor is now requires-python = ">=3.9".

New flags worth knowing about (agentguard serve)#

  • --audit-max-size-mb, --audit-max-backups, --audit-max-age-days, --audit-compress — rotation knobs (see above).
  • --audit-buffered (default true), --audit-queue-size, --audit-workers, --audit-overflow-path — buffered async audit logger. The hot path no longer blocks on the audit mutex; disk-overflow durability spills to <audit-log>.overflow.jsonl when the queue saturates. --audit-buffered=false restores the v0.4.x synchronous path.
  • --debug-pprof and --debug-pprof-port (default 6060) — localhost-only pprof listener. Off by default; tunnel via kubectl port-forward or ssh -L for remote profiling sessions.

New CLI subcommand#

  • agentguard check — one-shot policy check (or batch from JSONL stdin) against a local policy file without going through the HTTP server. Useful for CI gates and pre-commit hooks. See CLI.md.

Behavioral changes worth knowing about#

  • The dashboard chips audit entries by transport. SDK callers stay tagged sdk; MCP Gateway and LLM API Proxy entries carry mcp_gateway and llm_api_proxy respectively. Filter via /v1/audit?transport=mcp_gateway or agentguard audit --transport mcp_gateway.
  • /v1/check accepts schema_version: "v1" in the request body. Omitting it still defaults to v1; non-v1 values are rejected with 400. SDK clients on v0.4.1 already match the wire (the field is opaque to them); custom clients hand-rolling JSON should add it.
  • Histogram buckets for agentguard_*_duration_ms extend past 1 s (new 2500 ms, 5000 ms, 10 000 ms buckets). Existing dashboards still work; histograms with new buckets coexist with old data points (Prometheus computes summaries across both).

Rollback to v0.4.1#

Supported with one caveat: audit entries written by v0.5 binaries carry a transport field that v0.4.1 readers ignore but the field is preserved on disk. Downgrading is therefore lossy only if you need the v0.5 binary to re-read those entries with the field intact (the v0.4.1 binary will emit them through Logger.Query with Transport == "").

Steps:

  1. Stop the v0.5 server, MCP gateway, and LLM API proxy.
  2. Replace the central-server binary with v0.4.1.
  3. If you turned on built-in rotation, delete or move any rotated audit-*.jsonl[.gz] files out of the audit directory before starting v0.4.1 — v0.4.1 does not know how to walk a rotation chain.
  4. Restore your previous external rotation configuration if you turned it off.
  5. Start the v0.4.1 server.

Forcing a full replay#

Same as v0.4.0 → v0.4.1: agentguard migrate --reset-checkpoint --audit-log <path> deletes <path>.replay-checkpoint. The next server start performs a full replay (now walking the rotation chain) and writes a fresh checkpoint.


v0.5.0 → v0.5.1#

What happens automatically#

  • Nothing on the server side. No file rewrite, no policy schema change, no audit format change.
  • The central server, MCP Gateway, and LLM API Proxy all bump to v0.5.1; existing v0.5.0 audit logs replay cleanly, existing v0.5.0 policies load unchanged.

What you should do#

  1. Bump Python ≥ 3.10. v0.5.1 drops Python 3.9 (upstream EOL October 2025; the mcp extra already required >=3.10). pyproject.toml is now requires-python = ">=3.10". Users still on 3.9 should pin to agentguardproxy==0.5.0 or upgrade their interpreter.

    pip install --upgrade "agentguardproxy==0.5.1"   # 3.10+ only
    
  2. Update the framework adapters. If you wrote v0.5.0 code that worked around the composition-wrapper isinstance issue (e.g., Tool.from_function(func=lambda x: gt.invoke(x)) for LangChain, or skipped Agent(tools=[GuardedCrewTool(...)])), you can now pass the wrappers in directly. The v0.5.1 adapters subclass langchain_core.tools.BaseTool and crewai.tools.BaseTool natively. See ADAPTERS.md.

  3. Optionally silence the new update notice. Every subcommand of the agentguard binary (since v1.1.0: every subcommand except serve) asynchronously checks the GitHub Releases API at startup and prints a single stderr line if a newer release is published. Set AGENTGUARD_NO_UPDATE_CHECK=1 in scripted environments where stderr noise is unwanted. See CLI.md.

New surfaces#

  • AGENTGUARD_NO_UPDATE_CHECK environment variable — disables the v0.5.1 startup update-notice. Only the agentguard binary performs the check; the MCP gateway and LLM proxy never did.
  • make test-all / scripts/test-all.sh — single entry point for Go + policy YAML + Python SDK + TypeScript SDK suites with PASS / FAIL / SKIP summary; exits 1 if any suite failed. See CONTRIBUTING.md.

Rollback to v0.5.0#

Trivial. v0.5.1 introduces no on-disk state, no schema bumps, and no wire-protocol changes:

  1. Reinstall v0.5.0 binaries (go install …@v0.5.0).
  2. Reinstall the Python SDK at the v0.5.0 release: pip install --upgrade "agentguardproxy==0.5.0".
  3. Start. No data migration required either way.

The only behavioural difference an operator might notice: v0.5.0 Python SDK on CrewAI 1.x + pydantic 2.12 / langgraph 1.0 + langchain_core 1.x fails the framework's isinstance(thing, BaseTool) check — that's the bug v0.5.1 fixes. If you downgrade and run a recent framework, pin to the older crewai<1.0 / langchain<1.0 line.


v0.5.x → v0.7.0 (includes the v0.6 milestone)#

v0.5.2 was a maintenance release (toolchain refresh, no migration). v0.7.0 was never tagged or published — there is no v0.7.0 Go module version and no v0.7.0 PyPI release. The v0.6 milestone (persistence + multi-tenancy) was tagged only as V0.6.0, an uppercase tag go install can't resolve (PyPI does have agentguardproxy==0.6.0). The changes below first shipped in an installable release in v0.9.0: upgrade from v0.5.x straight to v0.9.0 or later and apply this section together with § v0.7.0 → v0.9.0. Full detail: releases/v0.7.0.md. (Corrected in v1.1.1: this section previously said upgrading directly to v0.7.0 was the supported path; v0.7.0 was never published.)

What happens automatically#

  • serve becomes stateful by default. First run creates agentguard.db (SQLite, WAL) in the working directory (--data-dir to relocate); approvals, rate-limit buckets, and cost accumulators now survive restarts. --persist=false restores the old pure-in-memory behaviour. No existing file is rewritten — the store is a new artifact.
  • No wire or format changes. schema_version: "v1", the /v1/... and /v1/t/{tenant}/... route families, and the audit JSONL (schema_version: 2) are backward-compatible.

What you should do#

  1. Give the process a writable --data-dir (or run --persist=false deliberately) and add agentguard.db + -wal/-shm to your backup plan — see OPERATIONS.md.
  2. Review action-keyed filesystem rules. Verdicts are now consistent across integration paths; CrewAI/MCP paths that previously omitted action now send it, so expect new (correct) matches.
  3. Optionally adopt the new operator surface: --fail-audit-log (outage-window denial audit on both proxies), --notify-spool (notification overflow spool), --audit-backend=store, agentguard tenant put|list|rm, and agentguard check --watch.

Rollback to v0.5.x#

Reinstall the v0.5.x binaries. They ignore agentguard.db entirely (delete it if you want a clean tree); pending approvals stored in it are lost, matching v0.5.x's in-memory behaviour.


v0.7.0 → v0.9.0#

What happens automatically#

  • Nothing. v0.9.0 is a stabilization release, not a feature or format change. There is no file rewrite, no policy-schema change, no wire-protocol change, and no audit-format change.
  • The /v1/check request/response shapes, the audit log (schema_version: 2 JSONL), the policy schema (version: "1"), and every CLI flag/subcommand are byte-for-byte compatible with v0.7. Existing audit logs replay cleanly; existing policies load unchanged; existing SDK clients and proxies interoperate without changes.

What changed#

  • The audit "tamper-evident" wording was corrected — documentation only. The audit log was always an append-only JSON-Lines log with no cryptographic sealing, and that is now what the README and FAQ say. No code path or on-disk byte changed. If your compliance posture relied on the word "tamper-evident," achieve it the way the docs now describe: forward the audit log to append-only / WORM storage (S3 Object Lock, a SIEM, or syslog).
  • The v0.9 surface stabilization is now documented in COMPATIBILITY.md: the policy schema, wire protocol, audit format, and CLI are stabilized (the freeze targets for 1.0), with additive-only becoming the hard rule from 1.0. This is intent, not a behavior change.

What you should do#

  1. Swap the binaries and SDKs to 0.9.0. No config or data changes are required.

    go install github.com/Caua-ferraz/AgentGuard/cmd/agentguard@v0.9.0
    go install github.com/Caua-ferraz/AgentGuard/cmd/agentguard-mcp-gateway@v0.9.0
    go install github.com/Caua-ferraz/AgentGuard/cmd/agentguard-llm-proxy@v0.9.0
    pip install --upgrade "agentguardproxy==0.9.0"
    # TypeScript SDK: not on npm at 0.9.0 — build it from plugins/typescript
    

    (Corrected in v1.1.1: this block previously ended with npm install @agentguard/sdk@0.9.0. That npm package is unrelated to AgentGuard; the TypeScript SDK was not published at 0.9.0. It is on npm as @lictorate/agentguard from 1.1.1.)

  2. (Optional) Forward your audit log to WORM storage if you want tamper-evidence — see the README audit bullet and COMPATIBILITY.md.

Rollback (there is no v0.7.0 build)#

v0.9.0 introduces no on-disk state, no schema bumps, and no wire-protocol changes, but v0.7.0 was never published, so there is nothing to reinstall at that version. Roll back to v0.5.2 instead — see Rollback to v0.5.x above: v0.5.x ignores agentguard.db, so pending approvals stored there are lost. (Corrected in v1.1.1: this previously said to reinstall the v0.7.0 binaries/SDKs.)


v0.9.0 → v1.0.0#

What happens automatically#

  • Additive store-schema migration on first boot. The approvals table gains three columns (consumed_at, resolved_via, resolved_from — the one-shot consumption stamp and resolution-actor fields) via guarded ALTER TABLEs, and two new tables (rate_consumption, cost_consumption) are created for multi-node reconciliation. Idempotent, additive-only, no rewrite of existing rows; pre-v1.0 approvals load as unconsumed/unstamped. No backup step is needed and agentguard migrate is not involved.
  • Everything else is untouched: /v1/check request/response shapes, the audit format (schema_version: 2), and the policy schema (version: "1") are byte-for-byte compatible with v0.9.

Behavior changes worth knowing about#

  • Approval resolutions are write-once. Re-approving an already-approved id (or re-denying a denied one) stays an idempotent no-op, but a conflicting re-resolution now returns 409 Conflict with a structured body instead of silently flipping the decision. Anything that relied on flip-by-re-POST must stop; that was the last-write-wins hole.
  • A resolved ALLOW is one-shot and time-boxed. The first /v1/check retry carrying the approval_id consumes it; later replays re-enter the approval flow. Honoring is bounded by --approval-validity (default 5m; 0 restores the unbounded pre-v1.0 window). Long-delayed retries that used to be honored will now come back as fresh approval requests.
  • Malformed streaming tool calls now fail closed. The LLM API Proxy refuses (and audits) a completed tool call whose assembled arguments are not valid JSON, instead of silently dropping it and going dark for the rest of the stream.
  • Domain matching is case-insensitive. A deny rule for evil.com now matches EVIL.com. Policies that (accidentally) relied on case-sensitive domain rules are evaluated case-insensitively.
  • Multi-node is opt-in. Nothing changes unless you set --store-dsn postgres://…; the zero-config SQLite default behaves exactly as in v0.9 (the reconcile ticker stays off). See OPERATIONS.md.

What you should do#

  1. Swap the binaries and SDKs to 1.0.0. No config or data changes are required for single-node deployments.

    go install github.com/Caua-ferraz/AgentGuard/cmd/agentguard@v1.0.0
    go install github.com/Caua-ferraz/AgentGuard/cmd/agentguard-mcp-gateway@v1.0.0
    go install github.com/Caua-ferraz/AgentGuard/cmd/agentguard-llm-proxy@v1.0.0
    pip install --upgrade "agentguardproxy==1.0.0"
    # TypeScript SDK: not on npm at 1.0.0 — build it from plugins/typescript
    

    (Corrected in v1.1.1: this block previously ended with npm install @agentguard/sdk@1.0.0. That npm package is unrelated to AgentGuard; the TypeScript SDK was not published at 1.0.0. It is on npm as @lictorate/agentguard from 1.1.1.)

  2. If you run (or plan to run) more than one replica: provision PostgreSQL, set --store-dsn postgres://… and a distinct --node-id per replica, and read the bounded-overshoot semantics in COMPATIBILITY.md before sizing --reconcile-interval.

Rollback to v0.9.0#

Supported. The schema changes are additive: a v0.9.0 binary reads a v1.0-touched SQLite store (the extra columns and tables are simply ignored). Two things degrade on rollback: one-shot consumption stamps stop being enforced (v0.9 predates them — previously-spent ALLOWs become replayable within their retention window), and any Postgres-backed deployment must return to single-node SQLite (v0.9 has no Postgres backend).


v1.1.0 → v1.1.1#

Coming from 1.0.x? Read the Compatibility section of CHANGELOG.md § 1.1.0 first. This section covers only 1.1.0 → 1.1.1.

What happens automatically#

  • Nothing on disk changes: no store schema, audit format or checkpoint change. /v1/check, the audit format (schema_version: 2) and the policy schema (version: "1") are unchanged.

Behavior changes worth knowing about#

  • agentguard-llm-proxy --listen :PORT refuses to start without --proxy-api-key. A listen address with no host binds every interface, but 1.1.0 treated it as loopback and started with no inbound auth. It now exits with status 2 and says --listen ":8081" has no host, so it binds every interface …. Use 127.0.0.1:PORT for loopback only, or set --proxy-api-key if you meant to listen on every interface.
  • The shipped configs/default.yaml changed for the example fetch and GitHub MCP servers. This only matters if you run that file itself; a copy you made earlier keeps its old rules.
    • fetch:* calls require approval. After approval, the mapped network check still applies, so only allow-listed hosts pass. In 1.1.0 the official fetch server's fetch:fetch tool matched no rule and was denied by default.
    • github:* is no longer in tool_scope_map. GitHub calls still require approval, and an approved call now runs. In 1.1.0 the mapped network check found no domain in GitHub's arguments and denied every call, approved or not.
  • go install builds show the update notice. The interactive subcommands of a binary installed with go install …@vX.Y.Z or @latest now check the GitHub Releases API at startup, as CLI.md describes; in 1.1.0 those builds reported commit=dev and skipped the check. serve still never checks. Set AGENTGUARD_NO_UPDATE_CHECK=1 to opt out.
  • agentguard version identifies more builds. A go install build prints agentguard 1.1.1 (module v1.1.1) instead of (dev), and a go build in a git checkout prints the short revision. A script that matched the literal (dev) needs updating.
  • make docker-run requires AGENTGUARD_API_KEY. It passes the key into the container and stops before building the image when the variable is unset. Without a key the server binds the container's own loopback, so the published port never answered.

What you should do#

  1. Swap the binaries and the Python SDK to 1.1.1.

    go install github.com/Caua-ferraz/AgentGuard/cmd/agentguard@v1.1.1
    go install github.com/Caua-ferraz/AgentGuard/cmd/agentguard-mcp-gateway@v1.1.1
    go install github.com/Caua-ferraz/AgentGuard/cmd/agentguard-llm-proxy@v1.1.1
    pip install --upgrade "agentguardproxy==1.1.1"
    
  2. TypeScript SDK: install it from npm and update your imports. The SDK is on npm as @lictorate/agentguard from 1.1.1. Before that it could only be built from plugins/typescript, where its package name was @agentguard/sdk, so the import path changes:

    npm uninstall @agentguard/sdk   # the old package name
    npm install @lictorate/agentguard@1.1.1
    
    // before
    import { AgentGuard } from '@agentguard/sdk';
    // after
    import { AgentGuard } from '@lictorate/agentguard';
    
  3. If you start the LLM proxy with --listen :PORT, change it to 127.0.0.1:PORT or add --proxy-api-key.

  4. If your MCP client config still launches npx -y @modelcontextprotocol/server-fetch (a package that never existed on npm, so that namespace was always empty) or the deprecated @modelcontextprotocol/server-github, switch to the launchers in examples/: uvx mcp-server-fetch and GitHub's ghcr.io/github/github-mcp-server image.

Rollback to v1.1.0#

Supported: nothing on disk changed. Rolling back brings back the --listen :PORT hole, where the proxy starts on every interface with no inbound auth, so use 127.0.0.1:PORT or set --proxy-api-key before you roll back. @lictorate/agentguard has no 1.1.0 release on npm; to roll the TypeScript SDK back, build plugins/typescript at the v1.1.0 tag.


v1.1.x → v1.2.0#

This section covers 1.1.0 and 1.1.1 → 1.2.0. Coming from 1.0.x? Read § v1.1.0 → v1.1.1 and the Compatibility section of CHANGELOG.md § 1.1.0 first.

1.2.0 fixes one high-severity policy bypass and nine medium-severity findings from a full local test of 1.1.1. Several of the fixes change what a policy you already have decides, so read Behavior changes before you upgrade.

What happens automatically#

  • No on-disk format changes. The store schema, the audit format (schema_version: 2), the replay checkpoint and the policy schema (version: "1") are unchanged, and 1.2.0 reads everything 1.1.x wrote.
  • New audit entries are written with secrets masked (see below). Entries already on disk are not rewritten.
  • The file audit logger rewrites the replay checkpoint after every rotation and on shutdown, not only at startup.

Behavior changes worth knowing about#

Policy evaluation

  • Compound shell commands are checked one command at a time. In 1.1.x a shell rule's glob matched the whole command line, and one * matched every operator in it, so allow: "ls *" also allowed ls /tmp; rm -rf /. A shell command that contains shell syntax (;, &&, ||, |, &, a line break, $( ), backticks, <( ), a subshell, a redirection) is now split into the simple commands a shell would run:

    • Whole-command deny and require_approval rules run first, as before.
    • Then each command is checked on its own (deny, then approval, then allow, then default deny), and the most severe verdict wins.
    • Each redirection target is checked as a filesystem write (>, >>) or read (<). /dev/null and descriptor duplications such as 2>&1 are ignored.
    • An allow pattern that contains shell syntax itself, such as cat * | head *, matches command by command.
    • A command the splitter can't handle safely (a heredoc, $(( )), unbalanced quotes, nesting deeper than 8 levels) is denied with deny:shell:unparseable_command.

    A command with no shell syntax is matched exactly as before. With the shipped configs/default.yaml:

    Command 1.1.x 1.2.0
    ls /tmp; rm -rf / ALLOW REQUIRE_APPROVAL (rm -rf *)
    ls /tmp && sudo rm -rf / ALLOW REQUIRE_APPROVAL (sudo *)
    echo x > /etc/passwd ALLOW DENY (deny:filesystem:write)
    cat README.md | head -5 ALLOW DENY: no rule allows head -5
    git status && git diff ALLOW ALLOW

    The fourth row is the one most likely to affect a working setup: a pipeline or chain is allowed only when every command in it is. Add allow rules for the commands your agents chain, or an allow pattern with the operator in it. Details: POLICY_REFERENCE.md.

  • Rule blocks that share a scope are merged. 1.1.x stopped at the first block for a scope that decided, so a second block for the same scope was ignored whenever the first matched: allow: "*" followed by a separate deny: "rm *" block allowed rm -rf /. Blocks with the same scope (in rules:, or in one agent's override:) are now merged at load, and each merge logs a warning. If two merged blocks set different rate_limits, or different cost limits, the policy no longer loads, since keeping either would silently drop the other. This is the one way a policy that loaded on 1.1.x fails to load on 1.2.0: serve exits at startup, and a hot reload keeps the previous policy and logs Policy reload failed.

  • network and browser checks that carry only a url are matched against the URL's host. POLICY_REFERENCE.md always said they were, but 1.1.x read only domain, so every such check was denied by default, even for an allow-listed host. Checks that 1.1.x denied can now be allowed. An explicit domain still wins, and the host is taken the way an HTTP client would: https://api.github.com@evil.com/ is checked as evil.com.

  • The MCP gateway checks the URL's host, not a domain argument next to it. For a tool mapped to network or browser, 1.1.x took the domain from a domain, host or hostname argument before the URL, so a model could pair an allow-listed domain with a URL on another host. With a url argument, the gateway (and the Python MCP adapter) now checks the URL's host; a relative or malformed URL gives no domain and is denied. A tool that takes a domain or host argument and no url is checked as before.

  • Scope names one or two edits from a built-in scope warn at load (scope "shel" is not a built-in scope — did you mean "shell"?). The policy still loads; custom scopes still work.

Audit trail

  • Secrets are masked by default. In 1.1.x only notifications were redacted; keys, tokens and passwords in an agent's command were stored verbatim in the audit log and shown by GET /v1/audit, the SSE stream, the dashboard and /api/pending. serve --audit-redact (on by default) now masks them there too, using the notification patterns (extended in 1.2.0 with sk-… keys, Google AIza… keys, GitHub token types, JWTs, PEM private keys and Authorization / x-api-key header values) plus the policy's notifications.redaction.extra_patterns. A broad extra pattern therefore now also masks audit content. The masking runs in the audit workers, not on the /v1/check request path. --audit-redact=false restores verbatim content and logs a startup warning. See OPERATIONS.md.
  • agentguard audit shows the newest entries first. In 1.1.x --limit 20 returned the 20 oldest matches. --order asc restores the old order. GET /v1/audit still defaults to oldest first; pass order=desc for newest first. The dashboard's history now loads the newest 200 entries.

Shipped configs/default.yaml (a copy you made earlier keeps its old rules)

  • find … -exec, -ok and -delete require approval.
  • The filesystem MCP server's edit_file, move_file and create_directory tools are denied like write_file. In 1.1.x they matched the fs:* allow.

Python SDK

  • The CrewAI adapter requires CrewAI 1.0 or newer and raises ImportError on older versions. On CrewAI 0.19x, a crew ran agent tool calls through a path the adapter doesn't wrap, so tools that looked gated weren't. The crewai extra is now crewai>=1.0,<2.0, which also fixes pip install agentguardproxy[all] resolving CrewAI 0.193.
  • The mcp extra allows MCP 2.x (mcp>=0.9,<3.0).

New surfaces#

  • serve --bind <host>: listen on one address. Without --api-key, only a loopback address is accepted; anything else exits with status 2.
  • serve --audit-redact, validate --strict (exit 1 when the policy loads with warnings), audit --order asc|desc, and agentguard --version.
  • GET /v1/audit?order=asc|desc (and the tenant mirror). Any other value returns 400.
  • Python: agentguard.__version__.
  • Go packages, all additive: policy.LoadFromFileWithWarnings; proxy.IsLoopbackHost and proxy.Config.Redactor / BindHost; audit.WithTransform, audit.EntryTransform, audit.Checkpointer, (*audit.FileLogger).EnableCheckpoints, audit.QueryFilter.Desc and audit.BufferedAsyncOpts.Transform; (*notify.Redactor).RedactRequest and RedactString.

What you should do#

  1. Validate your policy with the 1.2.0 binary before you swap the server:

    agentguard validate --strict --policy /etc/agentguard/policy.yaml
    

    An error means two blocks for one scope set different rate or cost limits; keep one. A WARN about merged blocks tells you which rules now apply together; one about a scope name is probably a typo.

  2. Replay your recent shell ALLOWs through 1.2.0 to see which chained commands it would stop. audit.jsonl is your 1.1.x server's audit log:

    jq -c 'select(.request.scope == "shell" and .result.decision == "ALLOW") | .request' audit.jsonl \
      | agentguard check --policy /etc/agentguard/policy.yaml --batch \
      | grep -v '^ALLOW'
    

    Add allow rules for the commands you want to keep allowing.

  3. Swap the binaries and the SDKs.

    go install github.com/Caua-ferraz/AgentGuard/cmd/agentguard@v1.2.0
    go install github.com/Caua-ferraz/AgentGuard/cmd/agentguard-mcp-gateway@v1.2.0
    go install github.com/Caua-ferraz/AgentGuard/cmd/agentguard-llm-proxy@v1.2.0
    pip install --upgrade "agentguardproxy==1.2.0"
    npm install @lictorate/agentguard@1.2.0
    
  4. If you use the CrewAI adapter on CrewAI 0.x, upgrade CrewAI to 1.x.

  5. If a script parses agentguard audit output in order, or depends on secrets appearing in the audit trail, pass --order asc or --audit-redact=false.

Rollback to v1.1.x#

Supported: nothing on disk changed format, and 1.1.x reads the checkpoint 1.2.0 writes. Rolling back brings back the compound-shell and duplicate-block bypasses, and new audit entries are stored unredacted again. Entries 1.2.0 wrote stay masked.


v1.2.x → v1.3.0#

1.3.0 adds prebuilt releases with one-line installers, agentguard setup, and the Claude Code integration, and reworks the command line. Policies decide exactly as in 1.2.0. What can surprise you is the command line: some commands that ignored part of what you typed now act on it.

What happens automatically#

  • No on-disk format changes. The store schema, the audit format, the replay checkpoint and the policy schema are unchanged, and 1.3.0 reads everything 1.2.x wrote.
  • Nothing is set up for you: agentguard setup writes a policy, a key, a data folder and a login service only when you run it and choose to.

Behavior changes worth knowing about#

Command line

  • Flags after an argument now apply. agentguard approve ap_1 --url https://guard.example used to approve on http://localhost:8080, because flag parsing stopped at ap_1. It now goes to the URL you gave, on every command.
  • A stray argument is an error (exit 2) instead of being ignored, for every command and for agentguard-mcp-gateway and agentguard-llm-proxy. Check your MCP client configs: if an --upstream command was split across several args entries ("--upstream", "fs:npx", "/tmp"), 1.2.x started the MCP server without /tmp; 1.3.0's gateway refuses to start. Put the whole command in one string.
  • agentguard validate <file> validates that file. 1.2.x ignored the argument and validated configs/default.yaml.
  • Exit status 2 for any command-line mistake, including running agentguard with no command and approve/deny without an ID (exit 1 before). help, -h and --help print to stdout and exit 0.
  • Output wording changed: approve/deny print Approved <id> / Denied <id> (was Action approve: approved), errors say what to do, and the update notice names the command that updates. Scripts should rely on exit codes.
  • agentguard server is the command's name. serve runs the same code for the whole 1.x line.

Settings you don't give

A flag always wins; these apply only when it is missing:

  • AGENTGUARD_URL sets the server for approve, deny, status and audit, and --guard-url for the MCP gateway and the LLM proxy. If you set it for the SDKs and run the gateway without --guard-url, the gateway now uses that server instead of http://127.0.0.1:8080.
  • --policy for server, validate and check: AGENTGUARD_POLICY, then configs/default.yaml (as before), then the installer's starter policy. check no longer requires --policy.
  • The API key agentguard setup saves is used by approve, deny, status, audit, the gateway and the proxy when neither --api-key nor AGENTGUARD_API_KEY is set. The server never reads it by itself; use --api-key-file.

MCP gateway

  • --reconnect-cap is applied. It used to be ignored; its default (60 s) is the old fixed maximum, so nothing changes unless you set it.

Starter policy

  • The shipped configs/default.yaml ends with an agents: claude-code: block (CLAUDE_CODE.md). It applies only to requests from agent claude-code. A copy you already have is not changed; agentguard setup offers to add the block when you connect Claude Code.

New surfaces#

  • agentguard setup — set up, update and uninstall from a menu.
  • agentguard help [<command>], and agentguard hook claude-code (run by Claude Code, not by you).
  • agentguard server --api-key-file <path>; --guard-url as another name for --url on approve, deny, status and audit.
  • Audit transport claude_code.

See CLI.md and CLAUDE_CODE.md.

What you should do#

  1. Look through scripts that call agentguard for flags after an argument, extra words, or parsing of approve, deny or help output.
  2. Check MCP client configs that start agentguard-mcp-gateway: every --upstream value must be one string.
  3. If AGENTGUARD_URL or AGENTGUARD_POLICY is set where the CLI, gateway or proxy runs, make sure it points where you mean.
  4. Swap the binaries: rerun the one-line installer, or go install github.com/Caua-ferraz/AgentGuard/cmd/...@v1.3.0. From 1.3.0 on, agentguard setup → Update does it too.

Rollback to v1.2.x#

Nothing on disk changed format, so 1.2.x reads what 1.3.0 wrote. Two things agentguard setup may have set up don't work with 1.2.x: the login service runs agentguard server, and Claude Code's hook runs agentguard hook claude-code, and 1.2.x has neither command. Before rolling back, open agentguard setup and choose Change settings → start at login: No, and Disconnect Claude Code. Then install 1.2.x with AGENTGUARD_VERSION=1.2.0 and the one-line installer.

v1.3.x → v1.4.0#

1.4.0 adds hooks for Cursor, Gemini CLI and Codex CLI, a tamper-evident audit log, agentguard test, session correlation and replay, agentguard report, Streamable HTTP upstreams for the MCP gateway, and an OpenAI Agents SDK adapter. Nothing was removed or renamed. A few behaviors are stricter, and two of them can change what a policy decides.

What happens automatically#

  • The store gains two columns. audit_entries gets parent_session_id and subagent on first start, on SQLite and Postgres. SQLite builds their indexes during that start, which can make it slower on a large audit table; it logs building index … (about N rows) first. Postgres builds them in the background with CREATE INDEX CONCURRENTLY, one replica at a time; queries work meanwhile. Nothing else in the store changes.
  • Rotated audit files carry a segment_id in their _meta header. Older files and checkpoints still match by created_at.
  • The audit log is not sealed unless you turn it on, so its lines stay byte-identical to 1.3. Installs that agentguard setup makes from now on are sealed.

Behavior changes worth knowing about#

Policy decisions

  • require_prior with an unreadable history. If the lookup behind a require_prior condition fails (a store or audit-log error), a deny or require_approval rule gated on it now fires, and an allow rule doesn't match. In 1.3 a deny rule silently didn't fire. With no history querier configured at all, nothing changes: the condition means "no prior action", as before. Write agentguard test cases with prior: to pin what your rules should do.

Shell rules

  • Commands inside bash -c, eval and launchers are checked. The script of a shell given -c, an eval, a here-string fed to a shell, and the command behind env, sudo, timeout, xargs, nohup and the other launchers listed in POLICY_REFERENCE.md are checked as commands of their own, and whole-line rules such as curl * | *sh also match inside them and inside longer command lines. In 1.3 bash -c 'rm -rf /tmp/x' passed a catch-all allow; it now needs the approval rm -rf needs. A deny on any part of a line now wins over an approval for the whole line, so under an allowlist sudo X is denied when X is denied. A bash -c script AgentGuard can't split (arithmetic, a heredoc, case) asks for approval. Run agentguard test on your own cases to see what changes for your policy.

Network rules

  • Hosts are matched in one canonical form. Other spellings of an address (hex, decimal or octal IPv4, IPv4-mapped IPv6, Unicode digits and dots, invisible characters, a trailing dot) now match a rule on the plain form. A request's domain field loses surrounding whitespace, a user@ prefix and a :port. A rule domain without a port now matches the host on any port, as URL requests already did; a rule domain with a port matches that port only.

API

  • GET /v1/audit validates since and until. A value that isn't RFC 3339, or an until before since, gets 400. 1.3 ignored both parameters and returned every entry. Write a + in a time offset as %2B (an unencoded + before the offset is accepted).

Python adapters

  • Conflicting alias arguments are denied. Tool input that sets command and cmd, or path and file_path, to different values is denied locally, without a server call, so the denial isn't in the server's audit log. Tool input that sets them to the same value, or only one of them, is checked as before.
  • parent_session_id comes from the Guard or the call, never from a tool's input.

MCP gateway

  • A host message without an id is forwarded only if it's a notification (notifications/*). A request method sent without an id, such as an id-less tools/call, is dropped and logged. MCP already treats it as invalid.

CLI

  • agentguard audit with --parent-session, --since or --until against a pre-1.4 server exits 1 instead of printing every entry, since that server would ignore the filters.

New surfaces#

  • agentguard hook cursor, hook gemini-cli, hook codex, and --fail-closed on every hook; connecting each agent from agentguard setup.
  • agentguard server --audit-seal, --audit-seal-key-file, --audit-anchor-interval; agentguard audit verify; GET /v1/audit/head.
  • agentguard test.
  • parent_session_id on /v1/check; GET /v1/sessions, GET /v1/sessions/{id}; since, until and parent_session_id on GET /v1/audit; agentguard audit --session --parent-session --since --until; the dashboard's Sessions view.
  • agentguard report.
  • agentguard-mcp-gateway --upstream-http and --upstream-header.
  • Python agentguard.adapters.openai_agents and the openai-agents extra.
  • Audit transports cursor, gemini_cli, codex_cli (and claude_code).

See CLI.md, CODING_AGENTS.md, COMPLIANCE.md and MCP_GATEWAY.md.

What you should do#

  1. If your policy uses require_prior, decide whether the stricter handling of an unreadable history is what you want, and add agentguard test cases for it.
  2. Run agentguard test with cases for the shell commands your agents run, especially ones wrapped in bash -c, timeout or env, to see which now need approval.
  3. Check scripts that call GET /v1/audit with since or until for the format: RFC 3339.
  4. Swap the binaries: agentguard setup → Update, rerun the one-line installer, or go install github.com/Caua-ferraz/AgentGuard/cmd/...@v1.4.0. Upgrade the SDKs with pip install --upgrade agentguardproxy==1.4.0 and npm install @lictorate/agentguard@1.4.0.
  5. To seal an existing install, add --audit-seal --audit-seal-key-file <file> to the server. Keep the key where agents can't write it, and publish anchors somewhere off the machine (the log line reaches journald, syslog or your SIEM).
  6. Connect Cursor, Gemini CLI or Codex CLI from agentguard setup if you use them.

Rollback to v1.3.x#

1.3 reads what 1.4 wrote: the two new store columns are ignored, and a sealed audit log is still valid JSON Lines (1.3 ignores the seal fields). Before rolling back, disconnect Cursor, Gemini CLI and Codex CLI in agentguard setup, since 1.3 has no hook for them, and remove --audit-seal flags from the server's command line if you added them by hand. A login service written by 1.4's setup passes --audit-seal; choose Change settings → start at login: No first, then set it up again after installing 1.3 with AGENTGUARD_VERSION=1.3.0 and the one-line installer.


v1.x to v2.0#

2.0.0 renames the project from AgentGuard to Vanzik. Every name that said AgentGuard says Vanzik now, and the old names are gone: no alias, no second binary, no fallback variable, and a set AGENTGUARD_* variable stops the program. That is the only breaking change: everything else in 2.0 is an addition (vanzik migrate --from-agentguard, the server adopting an agentguard.db) or a fix. The policy schema, the /v1/* wire protocol, the audit log format with its hash chain and seal, and every command's existing flags are as in 1.4.0, so your policy, audit log and database carry over as they are.

The rename has one risk worth reading this section for. The coding-agent hooks that agentguard setup connected live in each agent's own settings (~/.claude/settings.json, ~/.cursor/hooks.json, ~/.gemini/settings.json, ~/.codex/hooks.json) and run the agentguard program by its path. Most agents let a tool call through, unchecked, when a hook's program is missing. A hook left pointing at agentguard keeps working only as long as that program does, and stops checking anything the day it's deleted. The 2.0 installers and vanzik setup therefore migrate for you.

Upgrading a computer set up with agentguard setup or the installers#

Run the 2.0 installer as the user who set AgentGuard up (not with sudo):

curl -fsSL https://github.com/lictorate/vanzik/releases/latest/download/install.sh | sh
irm https://github.com/lictorate/vanzik/releases/latest/download/install.ps1 | iex

Once the new programs are installed, the installer runs vanzik migrate --from-agentguard. That command, which vanzik setup also runs before its menu (and which you can run yourself), does this, in order:

  1. Stops the AgentGuard server and removes its login service: the systemd user unit agentguard.service, the LaunchAgent com.lictorate.agentguard, or the Task Scheduler task AgentGuard. If that fails, it stops and changes nothing: AgentGuard keeps running as it was.
  2. Moves the folders, renaming them, so every file keeps its bytes: ~/.config/agentguard → ~/.config/vanzik (policy, API key, setup.json), and ~/.local/share/agentguard → ~/.local/share/vanzik (audit log and its rotated files, seal key, database, server log). On Windows: %APPDATA%\agentguard → %APPDATA%\vanzik and %LOCALAPPDATA%\AgentGuard\data → %LOCALAPPDATA%\Vanzik\data. If the Vanzik folder already has a file of the same name, the Vanzik copy is kept, AgentGuard's stays where it was, and the step is reported as failed for you to compare them. (A starter policy nobody edited is the exception: your policy replaces it.)
  3. Leaves a link ~/.config/agentguard → vanzik (a junction on Windows). An agent session that is open during the upgrade read its hooks when it started and keeps calling agentguard until it restarts; through the link, that program still finds its API key and port, so its calls are still checked. Delete the link once you've restarted your agents.
  4. Updates setup.json: paths into the moved folders point into the new ones. Nothing else in it changes.
  5. Renames the database agentguard.db to vanzik.db, with its -wal/-shm files. (vanzik server does the same by itself when it starts on the default database of a --data-dir holding an agentguard.db, so a server you run by hand keeps its approvals, rate-limit state and tenant policies too.)
  6. Points the hooks at vanzik. In each agent's settings, every entry AgentGuard wrote, "<…>/agentguard" hook <agent>, gets the vanzik program's path instead; --fail-closed and PowerShell's & stay, and so does every other key (the matcher, a timeout you changed, your own hooks beside it). The labels AgentGuard gave its Gemini CLI and Codex entries are renamed too. Each file that changes keeps its old copy as <file>.vanzik-backup. An entry is only touched if it is exactly what AgentGuard wrote, so a wrapper of your own such as /opt/agentguard-wrapper.sh hook cursor is left alone. A file that isn't plain JSON (Gemini CLI allows comments) can't be edited and is reported, with what to change by hand.
  7. Starts the server at login again, as vanzik.service, com.lictorate.vanzik or the task Vanzik, with the migrated settings, and waits for it to answer.

Run again, it finds nothing and says so. The old agentguard programs are not deleted, and neither are the old .agentguard-backup files; the summary lists what is left for you.

If any step fails, the installer still installs Vanzik but exits non-zero, and vanzik setup stops before its menu. Fix what the step says, then run vanzik migrate --from-agentguard again.

What you should do afterwards#

  1. Restart your agent sessions (Claude Code, Cursor, Gemini CLI, Codex) so they load the new hook.
  2. Trust the hook again in Codex: type /hooks and trust Vanzik's. Codex runs a changed hook only once it is trusted, so until then its tool calls are not checked. The migration reminds you when it changed Codex's hook.
  3. Rename your environment variables, wherever you set them (shell startup files, services, CI, container definitions). The migration lists the ones set in its own environment.
  4. Update MCP client configs that start agentguard-mcp-gateway or agentguard-llm-proxy: Claude Desktop, Cursor's mcp.json, Cline, Continue, Zed, Codex's config.toml. Change the program to vanzik-mcp-gateway / vanzik-llm-proxy. The migration lists the ones it finds, but doesn't edit them.
  5. Delete the old programs once nothing runs them: ~/.local/bin/agentguard* (or /usr/local/bin, or %LOCALAPPDATA%\Programs\AgentGuard\bin and its PATH entry), then the link ~/.config/agentguard.
  6. Upgrade the SDKs: pip uninstall agentguardproxy && pip install vanzik, and npm uninstall @lictorate/agentguard && npm install @lictorate/vanzik. Change the imports and class names (table below).
  7. Update what reads Vanzik's output: Prometheus queries, dashboards and alerts (agentguard_* → vanzik_*; the old series stop, they don't rename), webhook receivers that match the User-Agent, scripts that read X-AgentGuard-* response headers or a report's agentguard_version, and MCP or LLM clients that look for dev.agentguard/ or agentguard-refusal.

Servers you deployed yourself#

The migration changes nothing for a system-wide install: run as root it only lists what it finds (/etc/agentguard, /var/lib/agentguard, an agentguard.service system unit), because a unit or manifest you wrote names those paths, and moving them from under it would stop the server at its next restart. Move it when you're ready:

  • A systemd system unit (as in DEPLOYMENT.md): stop it; mv /etc/agentguard /etc/vanzik and mv /var/lib/agentguard /var/lib/vanzik; install the vanzik binaries; rename the unit to vanzik.service and change its ExecStart, paths, User= and environment to the new names; systemctl daemon-reload; start it. The server renames agentguard.db itself on its first start.
  • The container image is ghcr.io/lictorate/vanzik. Inside it the policy is /etc/vanzik/default.yaml, the data folder /var/lib/vanzik, and the user vanzik (the same uid, 10001, so a volume's permissions still fit). Mount your existing volume at /var/lib/vanzik instead of /var/lib/agentguard, mount your policy at /etc/vanzik/default.yaml, and rename -e AGENTGUARD_* to -e VANZIK_*.
  • PostgreSQL is unaffected: the store's tables have no product name in them, and your DSN names whatever database you created.
  • Multi-node: upgrade every node before relying on 2.0 dashboards or metrics; the wire protocol didn't change, so mixed 1.4/2.0 nodes check calls the same way meanwhile.

Behavior changes worth knowing about#

  • An AGENTGUARD_* variable that would be used stops the program. Vanzik never reads the old variables. But a vanzik server started with AGENTGUARD_API_KEY set (and no --api-key, --api-key-file or VANZIK_API_KEY) would otherwise run without the key its operator meant, so it exits naming VANZIK_API_KEY instead. The same goes for AGENTGUARD_POLICY (server, validate, check, test), AGENTGUARD_URL (the client commands, vanzik-mcp-gateway, vanzik-llm-proxy), and AGENTGUARD_URL, AGENTGUARD_API_KEY and AGENTGUARD_TENANT_ID in the SDKs (a ValueError from Guard(), a TypeError from new Vanzik()). A flag, an explicit argument, or the VANZIK_* variable makes the old one irrelevant. vanzik hook never refuses to run, since an agent lets the call through when its hook fails; when it can't check a call, its message names the old variable.
  • The dashboard's cookies are vanzik_session and vanzik_csrf. Upgrading restarts the server, so you sign in again either way.
  • An approval id kept in _meta["dev.agentguard/approval_id"] is not read; MCP clients retrying after an approval must send dev.vanzik/approval_id. A retry with the old key asks for a new approval.
  • The LLM proxy's own auth header is X-Vanzik-Proxy-Auth. A client still sending X-AgentGuard-Proxy-Auth gets 401 until it changes.

Renamed#

AgentGuard 1.x Vanzik 2.0
agentguard, agentguard-mcp-gateway, agentguard-llm-proxy vanzik, vanzik-mcp-gateway, vanzik-llm-proxy
AGENTGUARD_API_KEY, _URL, _POLICY, _TENANT_ID, _NO_UPDATE_CHECK, _DISTRIBUTION, _VERSION, _INSTALL_DIR, _DOWNLOAD_URL, _NO_MODIFY_PATH, _UNINSTALL, _PURGE VANZIK_API_KEY, _URL, _POLICY, _TENANT_ID, _NO_UPDATE_CHECK, _DISTRIBUTION, _VERSION, _INSTALL_DIR, _DOWNLOAD_URL, _NO_MODIFY_PATH, _UNINSTALL, _PURGE
~/.config/agentguard, ~/.local/share/agentguard ~/.config/vanzik, ~/.local/share/vanzik
/etc/agentguard, /var/lib/agentguard /etc/vanzik, /var/lib/vanzik
%APPDATA%\agentguard, %LOCALAPPDATA%\AgentGuard\data, %LOCALAPPDATA%\Programs\AgentGuard\bin %APPDATA%\vanzik, %LOCALAPPDATA%\Vanzik\data, %LOCALAPPDATA%\Programs\Vanzik\bin
agentguard.db vanzik.db
agentguard.service, com.lictorate.agentguard, task AgentGuard vanzik.service, com.lictorate.vanzik, task Vanzik
<file>.agentguard-backup <file>.vanzik-backup
X-AgentGuard-Policy-Ms, -Audit-Ms, -Total-Ms, -Parent-Session, -Proxy-Auth X-Vanzik-Policy-Ms, -Audit-Ms, -Total-Ms, -Parent-Session, -Proxy-Auth
MCP _meta prefix dev.agentguard/ dev.vanzik/
LLM proxy refusal id agentguard-refusal, error type agentguard_error, User-Agent: agentguard-llm-proxy/… vanzik-refusal, vanzik_error, vanzik-llm-proxy/…
Webhook User-Agent: AgentGuard/1.0 Vanzik/2.0
Report field agentguard_version vanzik_version
Metrics agentguard_*; example alerts AgentGuard* vanzik_*; Vanzik*
Dashboard cookies ag_session, ag_csrf vanzik_session, vanzik_csrf
Go module github.com/Caua-ferraz/AgentGuard lictorate.com/vanzik/v2
Go mcpgw.MetaPrefixAgentGuard, report.Report.AgentGuardVersion mcpgw.MetaPrefixVanzik, report.Report.VanzikVersion
PyPI agentguardproxy, import agentguard PyPI vanzik, import vanzik
Python AgentGuardError, AgentGuardDenied, AgentGuardApprovalRequired, AgentGuardApprovalTimeout, AgentGuardAuthError, AgentGuardTimeoutError; agentguard_tool_guardrail VanzikError, VanzikDenied, VanzikApprovalRequired, VanzikApprovalTimeout, VanzikAuthError, VanzikTimeoutError; vanzik_tool_guardrail
npm @lictorate/agentguard @lictorate/vanzik
TypeScript AgentGuard, AgentGuardOptions, AgentGuardError, AgentGuardDeniedError, AgentGuardApprovalRequiredError, AgentGuardApprovalTimeoutError, AgentGuardAuthError Vanzik, VanzikOptions, VanzikError, VanzikDeniedError, VanzikApprovalRequiredError, VanzikApprovalTimeoutError, VanzikAuthError
Image ghcr.io/caua-ferraz/agentguard ghcr.io/lictorate/vanzik
github.com/Caua-ferraz/AgentGuard, agentguard.lictorate.com github.com/lictorate/vanzik, vanzik.lictorate.com
Release archives agentguard_<v>_<os>_<arch> vanzik_<v>_<os>_<arch>

go install lictorate.com/vanzik/v2/cmd/...@v2.0.0 replaces go install github.com/Caua-ferraz/AgentGuard/cmd/...; a Go program that imports the packages changes its import paths to lictorate.com/vanzik/v2/….

1.x's own update path doesn't reach 2.0: agentguard setup → Update looks for an agentguard_* archive, which 2.0 doesn't publish, and stops with an error without changing anything. Use the 2.0 installer.

Rollback to v1.4.x#

  1. Stop Vanzik and its login service: vanzik setup → Uninstall… → Stop the server and don't start it at login.
  2. Put the folders back: delete the link ~/.config/agentguard, then move ~/.config/vanzik → ~/.config/agentguard and ~/.local/share/vanzik → ~/.local/share/agentguard (on Windows, the %APPDATA% and %LOCALAPPDATA% folders above), and rename vanzik.db (and its -wal/-shm files) back to agentguard.db. Change the paths in setup.json back.
  3. Restore each agent's settings from <file>.vanzik-backup, if you haven't changed them since, or change vanzik back to agentguard in the hook entries.
  4. Install 1.4: the 1.x installer with AGENTGUARD_VERSION=1.4.0, then agentguard setup → Change settings to start it at login again.

The policy, audit log and database are the same formats in both, so 1.4 reads everything 2.0 wrote.