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:
- The
v040_to_v041migration detects a headerless v1 audit file. - It writes a byte-for-byte backup to
<audit-log>.v040-backup(mode0600). - It rewrites the live file in place with a
schema_version: 2header record as the first line. - It verifies that the rewritten file parses cleanly and contains the same number of records as the backup.
- 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:
- Stop the v0.4.1 server.
cp <audit-log>.v040-backup <audit-log>— the backup is exactly the file v0.4.0 wrote.- Replace the binary with v0.4.0.
- 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/auditbut are not wired by default in v0.4.1. Continue to rotateaudit.jsonlexternally on this release. Rotation will be wired by default in v0.5; the rotator gzips rotated files and carries a_meta.rotated_frompointer 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
503withRetry-After. The previous behavior was silent state loss. If you scrapeagentguard_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
503on new logins; sign out idle tabs to free slots. /v1/audit?limit=is honored for the first time. The dashboard's existing?limit=200query now returns up to 200 entries (clamped to the newproxy.audit.max_limit, default1000). Scripts that relied on the hard-coded100will 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 pairingtime_windowwithrequire_priorin the policy rule, or removetime_windowentirely. 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
transportfield ("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. runServeconstructs 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 liveaudit.jsonlkeeps appending; once it crosses the size threshold, the rotator kicks in and rotated files start to appear asaudit.jsonl.YYYYMMDDTHHMMSSZ.gz(oraudit.jsonl.YYYYMMDDTHHMMSSZwith--audit-compress=false) alongside the active file.
What you should do#
Audit the audit log rotation chain. If you currently run
logrotate(or any other external rotator) againstaudit.jsonl, do one of:- Recommended: disable your external rotator. AgentGuard's built-in rotator handles size, age, and retention via flags.
- Or keep
logrotateand pass--audit-max-size-mb 0to disable AgentGuard's rotator. Usecopytruncatein yourlogrotateconfig (seeOPERATIONS.md).
Do not run both at once — the dual-rotator chain corrupts the
_meta.rotated_fromcontinuity and breaks startup replay's chain walk.Sweep your policy YAML for
time_windowwithoutrequire_prior. v0.5.0 promotes this from a WARNING to a load error. Find any rule withconditions.time_windowand no siblingconditions.require_priorand either pair them up or droptime_windowfrom the rule. v0.4.1'sagentguard_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.Decide on the new policy options:
mcp_toolscope — if you use the MCP Gateway, write at least one rule forscope: mcp_tool(configs/default.yamlships an example; seePOLICY_REFERENCE.md). The gateway dual-checksmcp_toolAND the mapped concrete scope (e.g.,shellornetwork), so omittingmcp_toolrules 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.unmappedsentinel — if you run the LLM API Proxy, decide your default-deny posture: write ascope: unmappedrule (deny or require-approval) for tool calls the proxy can't classify. The proxy returns synthetic refusal onunmappeddenials.
Deploy the new binaries (optional but the headline feature):
go install github.com/Caua-ferraz/AgentGuard/cmd/agentguard-mcp-gateway@v0.5.0go 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.yamlinto all three processes; each one hot-reloads it when it changes).Update Python SDK installs to Python 3.9+. v0.5 drops 3.8 (upstream EOL October 2024). The
pyproject.tomlfloor is nowrequires-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(defaulttrue),--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.jsonlwhen the queue saturates.--audit-buffered=falserestores the v0.4.x synchronous path.--debug-pprofand--debug-pprof-port(default6060) — localhost-only pprof listener. Off by default; tunnel viakubectl port-forwardorssh -Lfor 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. SeeCLI.md.
Behavioral changes worth knowing about#
- The dashboard chips audit entries by
transport. SDK callers stay taggedsdk; MCP Gateway and LLM API Proxy entries carrymcp_gatewayandllm_api_proxyrespectively. Filter via/v1/audit?transport=mcp_gatewayoragentguard audit --transport mcp_gateway. /v1/checkacceptsschema_version: "v1"in the request body. Omitting it still defaults to v1; non-v1 values are rejected with400. 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_msextend 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:
- Stop the v0.5 server, MCP gateway, and LLM API proxy.
- Replace the central-server binary with v0.4.1.
- 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. - Restore your previous external rotation configuration if you turned it off.
- 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#
Bump Python ≥ 3.10. v0.5.1 drops Python 3.9 (upstream EOL October 2025; the
mcpextra already required >=3.10).pyproject.tomlis nowrequires-python = ">=3.10". Users still on 3.9 should pin toagentguardproxy==0.5.0or upgrade their interpreter.pip install --upgrade "agentguardproxy==0.5.1" # 3.10+ onlyUpdate 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 skippedAgent(tools=[GuardedCrewTool(...)])), you can now pass the wrappers in directly. The v0.5.1 adapters subclasslangchain_core.tools.BaseToolandcrewai.tools.BaseToolnatively. SeeADAPTERS.md.Optionally silence the new update notice. Every subcommand of the
agentguardbinary (since v1.1.0: every subcommand exceptserve) asynchronously checks the GitHub Releases API at startup and prints a single stderr line if a newer release is published. SetAGENTGUARD_NO_UPDATE_CHECK=1in scripted environments where stderr noise is unwanted. SeeCLI.md.
New surfaces#
AGENTGUARD_NO_UPDATE_CHECKenvironment variable — disables the v0.5.1 startup update-notice. Only theagentguardbinary 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. SeeCONTRIBUTING.md.
Rollback to v0.5.0#
Trivial. v0.5.1 introduces no on-disk state, no schema bumps, and no wire-protocol changes:
- Reinstall v0.5.0 binaries (
go install …@v0.5.0). - Reinstall the Python SDK at the v0.5.0 release:
pip install --upgrade "agentguardproxy==0.5.0". - 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#
servebecomes stateful by default. First run createsagentguard.db(SQLite, WAL) in the working directory (--data-dirto relocate); approvals, rate-limit buckets, and cost accumulators now survive restarts.--persist=falserestores 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#
- Give the process a writable
--data-dir(or run--persist=falsedeliberately) and addagentguard.db+-wal/-shmto your backup plan — seeOPERATIONS.md. - Review
action-keyed filesystem rules. Verdicts are now consistent across integration paths; CrewAI/MCP paths that previously omittedactionnow send it, so expect new (correct) matches. - 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, andagentguard 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/checkrequest/response shapes, the audit log (schema_version: 2JSONL), 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#
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/agentguardfrom 1.1.1.)(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
approvalstable gains three columns (consumed_at,resolved_via,resolved_from— the one-shot consumption stamp and resolution-actor fields) via guardedALTER 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 andagentguard migrateis not involved. - Everything else is untouched:
/v1/checkrequest/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 Conflictwith 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/checkretry carrying theapproval_idconsumes it; later replays re-enter the approval flow. Honoring is bounded by--approval-validity(default5m;0restores 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.comnow matchesEVIL.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). SeeOPERATIONS.md.
What you should do#
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/agentguardfrom 1.1.1.)If you run (or plan to run) more than one replica: provision PostgreSQL, set
--store-dsn postgres://…and a distinct--node-idper replica, and read the bounded-overshoot semantics inCOMPATIBILITY.mdbefore 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 :PORTrefuses 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 …. Use127.0.0.1:PORTfor loopback only, or set--proxy-api-keyif you meant to listen on every interface.- The shipped
configs/default.yamlchanged 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 mappednetworkcheck still applies, so only allow-listed hosts pass. In 1.1.0 the official fetch server'sfetch:fetchtool matched no rule and was denied by default.github:*is no longer intool_scope_map. GitHub calls still require approval, and an approved call now runs. In 1.1.0 the mappednetworkcheck found no domain in GitHub's arguments and denied every call, approved or not.
go installbuilds show the update notice. The interactive subcommands of a binary installed withgo install …@vX.Y.Zor@latestnow check the GitHub Releases API at startup, asCLI.mddescribes; in 1.1.0 those builds reportedcommit=devand skipped the check.servestill never checks. SetAGENTGUARD_NO_UPDATE_CHECK=1to opt out.agentguard versionidentifies more builds. Ago installbuild printsagentguard 1.1.1 (module v1.1.1)instead of(dev), and ago buildin a git checkout prints the short revision. A script that matched the literal(dev)needs updating.make docker-runrequiresAGENTGUARD_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#
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"TypeScript SDK: install it from npm and update your imports. The SDK is on npm as
@lictorate/agentguardfrom 1.1.1. Before that it could only be built fromplugins/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';If you start the LLM proxy with
--listen :PORT, change it to127.0.0.1:PORTor add--proxy-api-key.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 inexamples/:uvx mcp-server-fetchand GitHub'sghcr.io/github/github-mcp-serverimage.
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, soallow: "ls *"also allowedls /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
denyandrequire_approvalrules 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
filesystemwrite (>,>>) or read (<)./dev/nulland descriptor duplications such as2>&1are 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 withdeny: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/passwdALLOW DENY ( deny:filesystem:write)cat README.md | head -5ALLOW DENY: no rule allows head -5git status && git diffALLOW 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.- Whole-command
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 separatedeny: "rm *"block allowedrm -rf /. Blocks with the same scope (inrules:, or in one agent'soverride:) are now merged at load, and each merge logs a warning. If two merged blocks set differentrate_limits, or different costlimits, 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:serveexits at startup, and a hot reload keeps the previous policy and logsPolicy reload failed.networkandbrowserchecks that carry only aurlare matched against the URL's host.POLICY_REFERENCE.mdalways said they were, but 1.1.x read onlydomain, 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 explicitdomainstill wins, and the host is taken the way an HTTP client would:https://api.github.com@evil.com/is checked asevil.com.The MCP gateway checks the URL's host, not a
domainargument next to it. For a tool mapped tonetworkorbrowser, 1.1.x took the domain from adomain,hostorhostnameargument before the URL, so a model could pair an allow-listed domain with a URL on another host. With aurlargument, 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 adomainorhostargument and nourlis 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 withsk-…keys, GoogleAIza…keys, GitHub token types, JWTs, PEM private keys andAuthorization/x-api-keyheader values) plus the policy'snotifications.redaction.extra_patterns. A broad extra pattern therefore now also masks audit content. The masking runs in the audit workers, not on the/v1/checkrequest path.--audit-redact=falserestores verbatim content and logs a startup warning. SeeOPERATIONS.md. agentguard auditshows the newest entries first. In 1.1.x--limit 20returned the 20 oldest matches.--order ascrestores the old order.GET /v1/auditstill defaults to oldest first; passorder=descfor 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,-okand-deleterequire approval.- The filesystem MCP server's
edit_file,move_fileandcreate_directorytools are denied likewrite_file. In 1.1.x they matched thefs:*allow.
Python SDK
- The CrewAI adapter requires CrewAI 1.0 or newer and raises
ImportErroron 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. Thecrewaiextra is nowcrewai>=1.0,<2.0, which also fixespip install agentguardproxy[all]resolving CrewAI 0.193. - The
mcpextra 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, andagentguard --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.IsLoopbackHostandproxy.Config.Redactor/BindHost;audit.WithTransform,audit.EntryTransform,audit.Checkpointer,(*audit.FileLogger).EnableCheckpoints,audit.QueryFilter.Descandaudit.BufferedAsyncOpts.Transform;(*notify.Redactor).RedactRequestandRedactString.
What you should do#
Validate your policy with the 1.2.0 binary before you swap the server:
agentguard validate --strict --policy /etc/agentguard/policy.yamlAn error means two blocks for one scope set different rate or cost limits; keep one. A
WARNabout merged blocks tells you which rules now apply together; one about a scope name is probably a typo.Replay your recent shell ALLOWs through 1.2.0 to see which chained commands it would stop.
audit.jsonlis 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.
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.0If you use the CrewAI adapter on CrewAI 0.x, upgrade CrewAI to 1.x.
If a script parses
agentguard auditoutput in order, or depends on secrets appearing in the audit trail, pass--order ascor--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 setupwrites 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.exampleused to approve onhttp://localhost:8080, because flag parsing stopped atap_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-gatewayandagentguard-llm-proxy. Check your MCP client configs: if an--upstreamcommand was split across severalargsentries ("--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 validatedconfigs/default.yaml.- Exit status 2 for any command-line mistake, including running
agentguardwith no command andapprove/denywithout an ID (exit 1 before).help,-hand--helpprint to stdout and exit 0. - Output wording changed:
approve/denyprintApproved <id>/Denied <id>(wasAction approve: approved), errors say what to do, and the update notice names the command that updates. Scripts should rely on exit codes. agentguard serveris the command's name.serveruns 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_URLsets the server forapprove,deny,statusandaudit, and--guard-urlfor 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 ofhttp://127.0.0.1:8080.--policyforserver,validateandcheck:AGENTGUARD_POLICY, thenconfigs/default.yaml(as before), then the installer's starter policy.checkno longer requires--policy.- The API key
agentguard setupsaves is used byapprove,deny,status,audit, the gateway and the proxy when neither--api-keynorAGENTGUARD_API_KEYis set. The server never reads it by itself; use--api-key-file.
MCP gateway
--reconnect-capis 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.yamlends with anagents: claude-code:block (CLAUDE_CODE.md). It applies only to requests from agentclaude-code. A copy you already have is not changed;agentguard setupoffers to add the block when you connect Claude Code.
New surfaces#
agentguard setup— set up, update and uninstall from a menu.agentguard help [<command>], andagentguard hook claude-code(run by Claude Code, not by you).agentguard server --api-key-file <path>;--guard-urlas another name for--urlonapprove,deny,statusandaudit.- Audit transport
claude_code.
See CLI.md and CLAUDE_CODE.md.
What you should do#
- Look through scripts that call
agentguardfor flags after an argument, extra words, or parsing ofapprove,denyorhelpoutput. - Check MCP client configs that start
agentguard-mcp-gateway: every--upstreamvalue must be one string. - If
AGENTGUARD_URLorAGENTGUARD_POLICYis set where the CLI, gateway or proxy runs, make sure it points where you mean. - 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_entriesgetsparent_session_idandsubagenton first start, on SQLite and Postgres. SQLite builds their indexes during that start, which can make it slower on a large audit table; it logsbuilding index … (about N rows)first. Postgres builds them in the background withCREATE INDEX CONCURRENTLY, one replica at a time; queries work meanwhile. Nothing else in the store changes. - Rotated audit files carry a
segment_idin their_metaheader. Older files and checkpoints still match bycreated_at. - The audit log is not sealed unless you turn it on, so its lines stay
byte-identical to 1.3. Installs that
agentguard setupmakes from now on are sealed.
Behavior changes worth knowing about#
Policy decisions
require_priorwith an unreadable history. If the lookup behind arequire_priorcondition 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. Writeagentguard testcases withprior:to pin what your rules should do.
Shell rules
- Commands inside
bash -c,evaland launchers are checked. The script of a shell given-c, aneval, a here-string fed to a shell, and the command behindenv,sudo,timeout,xargs,nohupand the other launchers listed inPOLICY_REFERENCE.mdare checked as commands of their own, and whole-line rules such ascurl * | *shalso match inside them and inside longer command lines. In 1.3bash -c 'rm -rf /tmp/x'passed a catch-all allow; it now needs the approvalrm -rfneeds. A deny on any part of a line now wins over an approval for the whole line, so under an allowlistsudo Xis denied whenXis denied. Abash -cscript AgentGuard can't split (arithmetic, a heredoc,case) asks for approval. Runagentguard teston 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
domainfield loses surrounding whitespace, auser@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/auditvalidatessinceanduntil. A value that isn't RFC 3339, or anuntilbeforesince, 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
commandandcmd, orpathandfile_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_idcomes from theGuardor 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-lesstools/call, is dropped and logged. MCP already treats it as invalid.
CLI
agentguard auditwith--parent-session,--sinceor--untilagainst 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-closedon every hook; connecting each agent fromagentguard setup.agentguard server --audit-seal,--audit-seal-key-file,--audit-anchor-interval;agentguard audit verify;GET /v1/audit/head.agentguard test.parent_session_idon/v1/check;GET /v1/sessions,GET /v1/sessions/{id};since,untilandparent_session_idonGET /v1/audit;agentguard audit --session --parent-session --since --until; the dashboard's Sessions view.agentguard report.agentguard-mcp-gateway --upstream-httpand--upstream-header.- Python
agentguard.adapters.openai_agentsand theopenai-agentsextra. - Audit transports
cursor,gemini_cli,codex_cli(andclaude_code).
See CLI.md, CODING_AGENTS.md,
COMPLIANCE.md and MCP_GATEWAY.md.
What you should do#
- If your policy uses
require_prior, decide whether the stricter handling of an unreadable history is what you want, and addagentguard testcases for it. - Run
agentguard testwith cases for the shell commands your agents run, especially ones wrapped inbash -c,timeoutorenv, to see which now need approval. - Check scripts that call
GET /v1/auditwithsinceoruntilfor the format: RFC 3339. - Swap the binaries:
agentguard setup→ Update, rerun the one-line installer, orgo install github.com/Caua-ferraz/AgentGuard/cmd/...@v1.4.0. Upgrade the SDKs withpip install --upgrade agentguardproxy==1.4.0andnpm install @lictorate/agentguard@1.4.0. - 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). - Connect Cursor, Gemini CLI or Codex CLI from
agentguard setupif 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:
- Stops the AgentGuard server and removes its login service: the
systemd user unit
agentguard.service, the LaunchAgentcom.lictorate.agentguard, or the Task Scheduler taskAgentGuard. If that fails, it stops and changes nothing: AgentGuard keeps running as it was. - 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%\vanzikand%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.) - 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 callingagentguarduntil 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. - Updates
setup.json: paths into the moved folders point into the new ones. Nothing else in it changes. - Renames the database
agentguard.dbtovanzik.db, with its-wal/-shmfiles. (vanzik serverdoes the same by itself when it starts on the default database of a--data-dirholding anagentguard.db, so a server you run by hand keeps its approvals, rate-limit state and tenant policies too.) - Points the hooks at
vanzik. In each agent's settings, every entry AgentGuard wrote,"<…>/agentguard" hook <agent>, gets thevanzikprogram's path instead;--fail-closedand 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 cursoris 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. - Starts the server at login again, as
vanzik.service,com.lictorate.vanzikor the taskVanzik, 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#
- Restart your agent sessions (Claude Code, Cursor, Gemini CLI, Codex) so they load the new hook.
- Trust the hook again in Codex: type
/hooksand 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. - 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.
- Update MCP client configs that start
agentguard-mcp-gatewayoragentguard-llm-proxy: Claude Desktop, Cursor'smcp.json, Cline, Continue, Zed, Codex'sconfig.toml. Change the program tovanzik-mcp-gateway/vanzik-llm-proxy. The migration lists the ones it finds, but doesn't edit them. - Delete the old programs once nothing runs them:
~/.local/bin/agentguard*(or/usr/local/bin, or%LOCALAPPDATA%\Programs\AgentGuard\binand its PATH entry), then the link~/.config/agentguard. - Upgrade the SDKs:
pip uninstall agentguardproxy && pip install vanzik, andnpm uninstall @lictorate/agentguard && npm install @lictorate/vanzik. Change the imports and class names (table below). - 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 theUser-Agent, scripts that readX-AgentGuard-*response headers or a report'sagentguard_version, and MCP or LLM clients that look fordev.agentguard/oragentguard-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/vanzikandmv /var/lib/agentguard /var/lib/vanzik; install thevanzikbinaries; rename the unit tovanzik.serviceand change itsExecStart, paths,User=and environment to the new names;systemctl daemon-reload; start it. The server renamesagentguard.dbitself 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 uservanzik(the same uid, 10001, so a volume's permissions still fit). Mount your existing volume at/var/lib/vanzikinstead 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 avanzik serverstarted withAGENTGUARD_API_KEYset (and no--api-key,--api-key-fileorVANZIK_API_KEY) would otherwise run without the key its operator meant, so it exits namingVANZIK_API_KEYinstead. The same goes forAGENTGUARD_POLICY(server,validate,check,test),AGENTGUARD_URL(the client commands,vanzik-mcp-gateway,vanzik-llm-proxy), andAGENTGUARD_URL,AGENTGUARD_API_KEYandAGENTGUARD_TENANT_IDin the SDKs (aValueErrorfromGuard(), aTypeErrorfromnew Vanzik()). A flag, an explicit argument, or theVANZIK_*variable makes the old one irrelevant.vanzik hooknever 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_sessionandvanzik_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 senddev.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 sendingX-AgentGuard-Proxy-Authgets 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#
- Stop Vanzik and its login service:
vanzik setup→ Uninstall… → Stop the server and don't start it at login. - Put the folders back: delete the link
~/.config/agentguard, then move~/.config/vanzik→~/.config/agentguardand~/.local/share/vanzik→~/.local/share/agentguard(on Windows, the%APPDATA%and%LOCALAPPDATA%folders above), and renamevanzik.db(and its-wal/-shmfiles) back toagentguard.db. Change the paths insetup.jsonback. - Restore each agent's settings from
<file>.vanzik-backup, if you haven't changed them since, or changevanzikback toagentguardin the hook entries. - Install 1.4: the 1.x installer with
AGENTGUARD_VERSION=1.4.0, thenagentguard 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.