Bringing Formal Verification to OpenCode: A Deep Dive into t
Key takeaways
- Static interception via OpenCode’s `tool.execute.before` hook enables pre‑execution verification.
- A Python sidecar running Z3 can evaluate path traversal, secret taint, and workflow automata in ~1.5 ms.
- Formal verification blocks unsafe tool calls before any side‑effects occur, eliminating many classes of attacks.
- The plugin’s submodule architecture keeps the core verifier up‑to‑date with upstream security patches.
- Extensible policy engine allows teams to add custom security automata for domain‑specific safeguards.
The rapid adoption of AI‑augmented development environments has exposed a hidden security surface: the ability of autonomous agents to invoke system tools (bash, file reads, edits, writes) without human oversight. While OpenCode’s TypeScript plugin architecture makes it easy to extend the platform, it also opens the door for malicious or careless tool usage. Inspired by Erik Meijer’s seminal paper Guardians of the Agents and the open‑source implementation by Nada Amin, a new plugin—opencode‑plugin‑guardians—brings static, formal verification to every tool call, turning OpenCode into a safer playground for AI agents.
---
How the Plugin Works
1. Interception via the TypeScript Hook
OpenCode exposes a tool.execute.before hook that fires just before any tool is executed. The Guardians plugin registers a handler that captures the tool name, its arguments, and the surrounding execution context. Because the interception occurs before any side‑effects, the plugin has a clean slate to reason about the request.
2. Offloading to a Python Sidecar
The captured payload is serialized and sent over a local Unix socket to a lightweight Python daemon. This daemon runs the guardians.verify() function from the guardians‑core submodule. Keeping the verification logic in Python isolates the heavy Z3 reasoning from the TypeScript runtime and allows the use of mature libraries for symbolic analysis.
3. Formal Verification in ~1.5 ms
Inside the daemon, three independent checks are performed:
* Z3 Path Containment – The tool arguments are modeled as symbolic strings and fed to the Z3 SMT solver. The solver proves whether a path could resolve to a directory traversal pattern such as ../../../../etc/passwd. If the solver finds a satisfying assignment, the request is rejected.
* Secret Taint Tracking – Files marked as secrets (e.g., .env, credentials.json) are automatically tainted. The verifier ensures that tainted data never reaches an output file, a shell command, or any external network call, preventing accidental leakage.
Security Automata – A small state machine enforces workflow policies like read‑before‑edit*. An edit operation on a file is only permitted if the same agent has previously performed a read on that file, mitigating blind overwrites.
All three checks are combined into a single Z3 query, keeping latency low (≈ 1.5 ms on a modern laptop) while providing strong guarantees.
4. Pre‑Execution Abort
If any check fails, the Python daemon returns a detailed violation report. The TypeScript side translates this into a thrown exception, aborting the tool call before any disk mutation occurs. The agent receives the error, can introspect the violation, and is forced to re‑plan a safe alternative.
---
Architectural Highlights
* Submodule Isolation – The core verification engine lives in guardians-core, a Git submodule that mirrors the upstream repository maintained by Nada Amin. This design keeps the OpenCode plugin lightweight and ensures that security patches flow in automatically.
* Language‑Agnostic API – Although the plugin is written for OpenCode’s TypeScript ecosystem, the verification daemon speaks a simple JSON‑over‑socket protocol. This opens the door for other IDEs or AI platforms to reuse the same guard without rewriting the logic.
* Extensibility – New policies can be added by extending the Z3 encoding or by plugging additional automata. Because the verification step is sandboxed, adding complexity does not jeopardize the host runtime.
---
Why Formal Verification Matters
Traditional runtime sandboxes (e.g., Docker, seccomp) react after a dangerous operation has already been attempted. In contrast, formal verification reasons about all possible executions of a given tool call before it ever touches the system. This pre‑emptive approach eliminates a whole class of attacks that rely on race conditions, timing windows, or obscure interpreter bugs. By leveraging Z3’s proven SMT capabilities, the Guardians plugin provides mathematically sound guarantees rather than heuristic heuristics.
---
Real‑World Scenarios
1. Preventing Path Traversal – An autonomous agent trying to read ../../../../etc/shadow will be blocked instantly, protecting sensitive system files.
2. Guarding Secrets – If an agent attempts to write a file that includes values from .env, the taint tracker flags the operation, preventing accidental credential exposure.
3. Enforcing Safe Edit Patterns – Consider a code‑generation workflow that must first read a source file before applying a edit. The security automaton ensures the edit is never performed on an unseen file, reducing the risk of destructive overwrites.
---
Getting Started
1. Clone the repository: git clone --recurse-submodules https://github.com/albertjoseph0/opencode-plugin-guardians
2. Install the Python sidecar: cd guardians-core && pip install -r requirements.txt
3. Start the daemon: python -m guardians_core.server &
4. Add the plugin to your OpenCode configuration, pointing to the TypeScript entry point.
5. Run an agent and observe the verification logs in the console.
The README provides detailed troubleshooting steps and a small test suite that demonstrates each security policy in action.
---
Looking Ahead
The current implementation focuses on file‑system interactions, but the verification framework is generic enough to cover network calls, database queries, and even GPU resource allocation. Future work could integrate policy as code where teams define custom automata in a YAML DSL, allowing organization‑wide security standards to be enforced automatically.
Moreover, coupling the Guardians plugin with a feedback loop—where agents learn from verification failures—could create self‑healing AI workflows that improve over time without human intervention.
---
Conclusion
By marrying Erik Meijer’s theoretical insights with Nada Amin’s practical implementation, the Guardians plugin demonstrates that formal verification can be both fast and developer‑friendly. OpenCode developers now have a robust, zero‑runtime‑overhead shield that stops unsafe tool calls before they happen, turning AI agents from powerful assistants into responsibly constrained collaborators.
We invite the community to experiment, contribute new policies, and share real‑world use cases. Together we can make AI‑augmented development not only more productive but also fundamentally safer.
---
Happy coding, and stay guarded!
Sources: https://github.com/albertjoseph0/opencode-plugin-guardians