SafeAgents: an open-source proxy that checks every tool call your coding agent makes before it runs
SafeAgents is a small local proxy that sits between a coding agent and its model server. It checks each tool call in the model's response before the harness receives it. A call it flags is replaced with a short text notice, so the harness gets a plain text reply and runs nothing. You point the agent's base URL at the proxy instead of the model server. All checks run locally on your machine: the proxy only forwards traffic to the model server you already use, and doesn't send your prompts, code or tool calls anywhere else unless you point the optional judge at a remote server. Each tool call goes through up to three checks: Two local checks that only need the request: whether the tool was declared by the harness, and whether the call reaches a host that appears nowhere in the conversation. The model's own earlier turns don't count as a source, so a URL the model came up with on its own is flagged. atif-scan by u/evalstate, which runs about 110 deterministic detectors on the pending call, in-process, with no model or network call: sandbox side channels, proxy and network bypasses, namespace escapes and reward hacking. Examples are curl to the cloud metadata endpoint, curl --noproxy posting ~/.netrc somewhere, or reading /proc/1/environ . Optionally, a judge model for milder findings. It can be any OpenAI-compatible server, including a small model on your own machine through llama.cpp, so this step can stay local too. It answers allow or block as JSON. It sees only the user's request, the call and the findings, not the agent's reasoning or tool outputs. It can add blocks but not remove them. Catching reward hacking in RL and evals The same detectors cover the tool calls a policy makes to game its reward instead of solving the task: writing its own reward file, editing the verifier's tests, or patching pytest so everything passes. Since safeagents is just a proxy in front of an OpenAI-compatible server, it can sit in front of the inference server used for rollouts or eval runs. In --log-only mode it records these attempts without changing the trajectories, which gives a measure of how often a model tries to cheat. In blocking mode, the call is replaced with a notice and never runs. Some practical details: It handles OpenAI Chat Completions and Anthropic Messages, streamed or not. Text is forwarded as it arrives; a tool call is held until its arguments are complete. The local checks take around 10–20 ms per call on an M-series Mac. The judge is only called for calls that already raised a finding. --log-only checks every call without changing anything, which is the recommended way to start. Hosts you trust can be added with --allow-host . The repo has setup guides for 12 harnesses. Six of them (pi, Claude Code, OpenCode, Qwen Code, OpenHands, DeepSeek Harness) are tested end to end in CI: the real harness runs through the proxy against a scripted model, and the tests check that flagged calls don't execute and clean ones do. Next steps are a small fine-tuned decision model for malicious tool calls and a public benchmark for it. Reports of interesting catches and of false positives are both useful. Apache 2.0, runs locally: github.com/huggingface/safeagents