October 19, 2026
Managing AI Agents and your ‘Claws’
TLDR: This article is introducing the problem space of security for AI Agents and describes a project I have recenly vibe coded that helps…

By Steve Fisher
14 min read
TLDR: This article is introducing the problem space of security for AI Agents and describes a project I have recenly vibe coded that helps tackle some of the issues, namely how AI Agents can work but with Humans remaining in control: https://github.com/stevef1uk/agent-gateway-runtime.git
About Me
I have been around since punch cards were the way one programmed computers, ok at a school computing club and I have worked in IT since graduating with a science degree, so I have seen lots of technology change. I have worked in SMEs, software companies, a global consultancy and lastly for myself so overall I must have over 43 years of experience.
The use of AI coding tools and agentic frameworks is still very new. Like a lot of IT professionals I have been tracking the rise of AI since ChatGPT burst onto our new feeds. When it did, I read and experimented with it. I must thank Ed Donner, Dr John Krohn, Hadolin de Ponteves and Kirill Eremenko for their excellent training materials.
I am semi retired living in the French Alps. I work part of the autumns and springs but as much of the winter as I can on a fully remote, part time (4 days a week) basis and I currently have availability for winter 2026. My LinkedIn page: https://www.linkedin.com/in/stevenjohnfisher
AI Agents and Tools
The underlying LLM models are basically just fancy statistical token predictors and comprise of layers upon layers of numbers which need to be 'crunched' with tuned sets of weights (more numbers) at each layer to get the models to produce the most desired output.
LLMs by themselves are cool, but in an abstract mathematical way. They only become useful when a software harness wraps them. ChatGPT was one of the first of these and added various dimensions to make them way more useful for human chat sessions.
The rise of harness engineering is ongoing to make the underlying LLMs more useful for different tasks. Coding Agents is where I am seeing the most innovation leading to a proliferation of Vive Coding and often poorly constructed software colloquially called AI Slop.
A number of vendors have produced frameworks to make writing AI Agent really easy. I have tried a lot of them and liked the CrewAI and LangGraph (LangChain) ones although OpenAI's is very popular. I used n8n AI Agents in workflows heavily for a client and this uses LangGraph under the hood.
All of these frameworks use LLMs to call Tools in loops to achieve an objective. A Tool can be anything and often involves calling APIs to get or update data and the Model Context Protocol is often described the USB-C drive for AI Agents. It describes what tools and how those tools should be used for AI Agents to use.
It is really trivial to create code to create Agents and Agents can themselves create Agents to work on sub-tasks. Here is some sample code that should be self describing:
from langchain.agents import create_agent
def add(a: float, b: float) -> float:
"""Add two numbers."""
return a + b
agent = create_agent(
model="anthropic:claude-sonnet-5-5",
tools=[add],
)
result = agent.invoke({
"messages": [
("user", "What is 1234 + 5678?")
]
})
print(result["messages"][-1].content)from langchain.agents import create_agent
def add(a: float, b: float) -> float:
"""Add two numbers."""
return a + b
agent = create_agent(
model="anthropic:claude-sonnet-5-5",
tools=[add],
)
result = agent.invoke({
"messages": [
("user", "What is 1234 + 5678?")
]
})
print(result["messages"][-1].content)The code above uses the LangChain python library to define a simple tool: add, and then creates an agent providing it with the LLM model to use plus the single tool and then calls it passing the text to process using the tool and finally it prints the result.
There are No Common Security Standards for AI Agents
Given my background of producing IT Services to financial institutions I have always had to worry about IT Security and how to secure APIs etc. The industry standards here are well known, SSO and Role Based Access Controls tied to Principals (Employees or Cloud Service Accounts) are well understood and applied. TLS, OAuth2, JWTs and other security standards normally with three letter acronyms abound!
In the Agentic AI world we have a number of challenges:
- How do we identify Agents?
- How do we control what Agents are allowed to call what Tools or interact with MCP Servers?
- How do we enable delegated authority for Agents?
- Can the authorisation be decided per call incontext?
- How do we prevent Agents from being hijacked or manipulated?
- How do we avoid Agents holding sensitive credentials?
- How do we control the 'blast radius' of a compromised Agent?
- How do we handle Agent to Agent Chains?
- When does a Human need to Approve an Action?
- How do we Audit what happened and when?
- How de we revoke delegated authorities?
- How do we verify the supply chain?
I was thinking about the above on one of my regualr morning mountain walks. On my return I sued Claude, ChatGPT and OpenCode to design a solution and then vive coded it!
With AI Tooling One can Deliver a Lot in a Weekend!
For now, I have chosen to keep the software (all Go) private in my local Gittea repo. From this I have produced the public GitHub repo which uses Docker images of my code for the demos (link above). I dusted off my secure Packager repo to enable me to encrypt my binaries and licence them. I gave all the images I uploaded to DockerHub a one year or so license, but that can easily be extended and I have made these completely free for individuals. Before the license expires all someone has to do is email me for a much longer term licence file. The onc currently provided in the repo are as follows:
The public repo has a number of demonstrations, including bash scripts and UIs. The most 'sexy' demos are those where the user is notified by a Telegram message, which has link to the provided Console for the user to approve.
Here are 3 screenshots which show the flow as Demo 2 is run with Telegram integration enabled:
When I announced this project on Hacker News someone uncharitably described this project as looking like typical AI Slop. I asked OpenCode, who wrote it for me in a weekend (with me providing feedback and testing) and guidance if that was a fair criticism and it gave me this table:
The Architecture of the Agent Gateway
The logical digram is shown below.
The state is held in a Postgres DB and Redis. The key components are all stateless so they can be scaled horizontally with load balancers added in front of them. However, I have run performance testing, which highlighted some software architecture issues which have been fixed.
The core components of the Agent Gateway are described below:
- gateway (:8080) — Policy Enforcement Point: reverse-proxies agent tool calls to upstream APIs after resolving identity and re-authorizing every request; manages approvals, revocation, and the admin API; appends audit events. Go, chi router, golang-jwt, go-spiffe (mTLS SVIDs), Redis jti revocation.
- gateway egress proxy (:8088) — Optional forward proxy (HTTP + CONNECT blind tunnel) for sandboxed agent egress; resource = destination host, action = HTTP method; blocks tunnelling to internal services. Same gateway binary.
- authz (:8081) — Policy Decision Point: delegation CRUD + POST /v1/check decision API; mints the first token per delegation; OIDC verification of the human's ID token. Go, coreos/go-oidc; built-in BasicAuthorizer or OPA (shells out to opa eval on a hot-reloaded Rego file).
- tokensvc (:8082) — Mints short-lived, delegation-scoped JWTs against a per-delegation agent secret; RFC 8693 token exchange with downscoping; per-IP rate limiting. Go, golang-jwt (HS256). web (:8083) — Admin console / guided demo / OPA policy playground; thin proxy over authz, gateway, tokensvc; OIDC authorization-code sign-in with server-side sessions and an IdP reverse proxy. Go, vanilla static HTML.
- agentdemo — CLI demo client that walks the full narrative (delegate → mint → call → approval → deny → revoke). Go, uses pkg/agent. agent SDK (pkg/agent) — Framework-agnostic client for agents: get token, call tool, approve. Plain Go HTTP. authzclient (pkg/authzclient) — Tuned HTTP client for the hot gateway→authz hop. Plain Go HTTP.
- Dex (:5556) — OIDC identity provider for human sign-in; designed to be swapped for Okta/Entra/Keycloak with no code changes. Dex v2.41.
- PostgreSQL (:5432) — Durable state: delegations, approvals, append-only audit_events; embedded migrations via go:embed + advisory locks. pgx/v5.
- Redis (:6379) — Ephemeral state only: token (jti) revocation, optional authz decision cache, rate limiting. go-redis/v9.
- OPA — Policy-as-code (Rego) evaluated by the opa binary with hot reload; optional alternative to the built-in authorizer. Support packages (internal/) — delegation domain model, approval (action-hash-bound, single-use), audit (JSON/Postgres writers), revocation, auth (JWT), identity (OIDC/SPIFFE verifiers), notify (webhook/Telegram), rate limit, ssrf guard, httpx security headers, config (12-factor env).
The Authorization Loop
- Human (SSO) ──► POST /v1/delegations (agent, resource, actions, limits, cap, expiry, id_token) 2 authz verifies the ID token against the OIDC provider (JWKS), binds delegation.user_id = token.subject (client-asserted names can only agree with it, never override it) 3 Agent ──► POST /token {delegation_id} tokensvc refuses revoked/expired delegations; JWT ~= 5 min, embeds jti 4 Agent ──► any tool call on the gateway, Bearer 5 gateway resolves principal (JWT w/ revocation check, or SPIFFE SVID) 6 gateway ──► authz /decision {principal, delegation, action} 7 Policy: resources ⊆ scope, actions ⊆ scope, transaction limits, approval rules → ALLOW | REQUIRE-APPROVAL | DENY 8a ALLOW → forward to UPSTREAM_URL, audit allow 8b HOLD (202) → approval created, bound to (delegation, action_hash), NOT executed; the approval is single-use 8b' notification → gateway pushes an approval.required webhook (HMAC-signed) to operator automation — n8n / Slack / Teams / PagerDuty — so the human learns without watching the console; the console also shows a pending badge + toast on its approval poll 8c DENY → refuse in place, audited; nothing forwarded 9 Human decides the pending approval (console, or Approve/Deny from the notification card via the operator API); a retry with the approved binding executes exactly once 10 Revoke: delegation revoked_at set → decisions deny instantly (authz) and even still-valid JWTs are refused at the gateway (redis jti check)
Performance Measured of the Agent Gateway
The benchmarking script is contained in the public repo. The image below is taken from the Benchmark document in the same repo that OpenCode produced for me. I ran this on a Linux box running on hardware a few years old now.
The Core Services Have been Security Scanned
Since Agent Gateway is a security tool it would have been negligent of me to not get OpenCode to run Zap OWASP Proxy tests against each service, govulncheck and Trivy image scans. I am sure more checks could be done, but I wanted to finish the core product in a weekend.
The software is tested with unit and integration tests.
Beyond the scan tooling, the code itself embeds security checks that are tested: SSRF/IP validation (internal/ssrf), egress proxy refusal to tunnel internal services (internal/gateway/proxy/proxy_test.go), rate limiting, HMAC-signed approval webhooks, and admin endpoints gated by X-Admin-Token.
How does this Agent Gateway Project Help With the AI Agentic Security Challenges
The points raised above have all been consided by this project:
- How do we identify Agents?
Agents authenticate with their own identity, never the human's: a short-lived delegation-scoped JWT (minted by tokensvc against a one-time per-delegation agent secret) or a SPIFFE/SPIRE mTLS SVID (X-Delegation-ID header binds the SVID to a delegation). Claims carry agent_id, user_id, delegation_id.
- How do we control what Agents can call / which Tools or MCP Servers?
Delegations carry explicit resource + action allowlists. Every call is re-authorized at the gateway (POST authz /v1/check with resource, action, args). The egress proxy (:8088) treats destination host = resource and HTTP method/CONNECT = action — all outbound traffic, including MCP/external tool calls, passes the same policy pipeline (OPA/Rego or built-in rules).
- How do we enable delegated authority?
The human (verified via OIDC ID token) creates a delegation: resources, actions, limits, expiry, approval rules, MaxDepth. Authz returns a one-time agent secret + first token. Child delegations are only created via Attenuate() — strictly narrower than the parent.
- Can authorisation be decided per call, in context? Y
Yes — core design. Each call is a fresh POST /v1/check with full context (delegation, agent, user, resource, action, args). OPA/Rego is evaluated per call (optional short-TTL Redis cache); the authz check always precedes approval consumption, so policy and revocation apply mid-session.
- How do we prevent Agents being hijacked or manipulated?
5-minute default tokens with jti + instant Redis revocation; tokens valid only for their single delegation; admin API gated by X-Admin-Token; approver binding (approver_id must equal the delegation's verified subject); per-IP rate limiting; SSRF guard; egress host allowlists with internal services non-tunnelable.
- How do we avoid Agents holding sensitive credentials?
Agents never see user passwords, cookies, refresh tokens, or raw API keys. They hold only a scoped token derived from a one-time secret (stored as SHA-256 digest; digest never leaves authz). Upstream sees identity headers (X-Auth-User, X-Auth-Agent, X-Delegation-ID) injected by the gateway, not agent-held human credentials. Token exchange can downscope further.
- How do we control the blast radius of a compromised Agent?
The delegation is the blast radius: resource/action allowlists, limits, TTL, MaxDepth. Revocation is immediate at the PEP even while tokens are cryptographically valid. Approvals are single-use and action-hash-bound (SHA-256 of resource+action+args — changed details = new hash = re-approval). Everything is audited for forensics.
- How do we handle Agent-to-Agent chains?
Parent/child delegations with mandatory attenuation (Attenuate(), MaxDepth) — a child can never exceed its parent's authority, and each hop keeps its own delegation_id through checks and audit.
- When does a Human need to approve?
Whenever the delegation's ApprovalRule marks an action high-risk (e.g., over a monetary cap): gateway returns 202, records an approval bound to (delegation_id, action_hash), notifies via HMAC-signed webhook or Telegram; the human approves via the web console or automation. Approvals are consumed single-use and expire; revocation beats a pending approval.
- How do we audit what happened and when?
An append-only event per decision: request_id, user/agent/delegation ids, tool, resource, action, args_hash, outcome, reason, policy_id, approval_id, status, duration. Written as stdout JSON lines (dev) or to Postgres audit_events (prod); viewable in the web console, ready for SIEM streaming.
- How do we revoke delegated authorities?
Two levels, both immediate: DELETE authz /v1/delegations/{id} (re-checked on every decision — revoke beats token validity and pending approvals) and POST gateway /v1/tokens/revoke (Redis jti, kills individual tokens instantly). TTL expiry handles the passive case.
- How do we verify the supply chain?
Deliberately tiny dependency set (chi, pgx, go-redis, go-oidc; zero generated code), govulncheck clean, Trivy HIGH/CRITICAL-clean images, multi-arch ELF verification, and shipped images are encrypted + licence-gated via secure-packager with RSA licence tokens and a key-drift guard before builds.
How to Integrate Agent Gateway into Your Environment
The four integration patterns
Pattern A — base-URL cutover (the one-line change) recommended first
Agents read their tool endpoints from configuration (env var, settings file, MCP client config). Point that configuration at the gateway instead of the back end and hand the agent one delegation token to put in Authorization: Bearer …:
Before: BASE_URL=https://orders.internal.corp (agent calls directly)
After: BASE_URL=https://agent-gateway.internal.corp/orders
TOKEN=<the agent's delegation token>Before: BASE_URL=https://orders.internal.corp (agent calls directly)
After: BASE_URL=https://agent-gateway.internal.corp/orders
TOKEN=<the agent's delegation token>Why this is realistic: every agent framework takes its tool locations from configuration — the deployment artifact changes, the agent's logic does not. Delegations are per agent/team, created in the admin console; the audit trail then shows every legacy agent's traffic with a name, an owner and a scope.
Pattern B — transparent network insertion (zero agent change)
For fleets you cannot reconfigure: cut over at the network layer instead.
DNS/VIP change: orders.internal.corp → formerly the backend,
now resolves to the gateway, upstream routed internallyDNS/VIP change: orders.internal.corp → formerly the backend,
now resolves to the gateway, upstream routed internallyAgents keep calling the same hostname with their existing code path. What changes for them: responses come back 401 until they present credentials that the gateway accepts. So roll this gradual: per tool, page the owner, hand their agent a delegation token, flip the DNS. The gateway's audit trail gives you the coverage map: every 401 has an unauthed caller behind it.
Pattern C — MCP servers
MCP traffic is JSON-RPC over HTTP (streamable HTTP/SSE transports), and the MCP client is always configured with the server URL — the same leverage as Pattern A: point the client at the gateway, put the real MCP server behind it as UPSTREAM_URL.
Two granularities, both working today:
Enforcement levelWhat you getHowPer server(day one)every MCP session against that server is governed: delegation, scope, cap, audit, approval gategateway fronts the MCP server; JSON-RPC calls arrive as ordinary HTTP; the gateway derives tool=/mcp, action=POSTPer tool(roadmap)each tools/call judged by its own params.name → tool-scoped policyan MCP filter in the gateway parses the JSON-RPC body and re-derives resource/action per call (tracked as a roadmap adapter)
For self-operated MCP servers there is a variant worth knowing: wrap the MCP server with the gateway agent middleware (a thin server that requires the delegation JWT before forwarding) if you prefer enforcement to live next to the server rather than in front of it.
Pattern D — egress control so nobody can bypass
In enterprise topology the gateway is inserted only if agents cannot shadow route around it. Standard belt-and-braces:
- Kubernetes
NetworkPolicy: agent pods may egress only to the gateway; the gateway (or the mesh) is the only identity allowed to reach the back end. - VM estates: egress firewall rules per agent segment, same principle.
- Regular expression review of the audit trail: tool names appearing without a gateway request id are a bypass signal.
This is what turns "we prefer agents use the gateway" into "agents go through the gateway," which is also what the auditors will ask for.
What About OpenClaw
This is my current focus. I lost a lot of time trying to get NemoClaw running on my Linux development machine but kept encountering product issues, Then I switched to using Openshell as the sandbox to run internally a custom built docker image ( which runs OpenClaw within Openshell all in the public repo).
I am still working on this and have demonstrated it running on my Linux Box and on my Mac with Telegram messages asking me to approve all OpenClaw requests that are not simple HTTP GETs or POST to LLM Model providers.
I use a Go forward proxy (also in the public repo) within the custom docker image to bridge the gap between the Openshell sandbox and the Agent Gateway. It turns ever outbound network connection from the sandboxed agent into an authorisation decision.
Some screenshots from my test scripts:
The Public Repo's Demos
I have provided a number of demos.
- Demo 1 (shell) — shows the basic flow and functionality
- Demo 2 (UI) — shows Demo 1 but in a Web UI
- Demo 3 (UI) — demostrates the Open Policy Agent capability and hot-reload and recovery capability
- Demo 4 (shell) — shows how a user's API can be protected
- Demo 5 (shell) — outbout egress via the gateway proxy demonstration
- Demo 6 — OpenClaw confined to an OpensShell Sandbox integrated with Agent Gateway for Human authorisations
Agent Gateway: Delegation Controls
These controls are available on each delegation, per user and per agent.
Identity and scope
- Agent identity (
agent_id): Ensures the agent matches the delegation. - User identity (
user_id): Binds the delegation to the verified user. - Resources (
resources[]): Defines which resources the agent can access. - Actions (
actions[]): Defines permitted operations: read, create, update and delete. - Expiry (
expires_in_seconds): Sets when the delegation expires. - Delegation depth (
max_depth): Limits how many levels of agent-to-agent delegation are allowed.
Limits and approvals
- Spend cap (
limits.spend_per_order): Orders above the cap are held for approval. - Count limit (
limits.max_count): Requests exceeding the limit are denied. - Custom limits (
limits.<name>): Available through the API and OPA, but not enforced by the built-in engine. - Approval rules (
approval_rules[]): Require human approval when specified conditions match.
Revocation and token metadata
- Revocation (
DELETE /v1/delegations/{id}): Immediately disables a delegation. - Scopes (
scopes[]): Supplies metadata for tokens and OAuth.
Where can these controls be configured?
- Console: Supports agent identity, user identity, resources, actions, expiry, delegation depth, spend caps and revocation.
- API: Supports all listed controls.
- OPA: Supports policy checks for resources, actions, spend caps, count limits, custom limits and approval rules. Identity, user verification, expiry and revocation are pre-checked outside OPA. Delegation depth and scopes are not evaluated by OPA.
Conclusions
Vibe Coding is now mainstream and one can produce complex software at minimal (or even zero) cost. This project is my attempt to help provide a solution to the security challenges arising from the Agentic Era and it would be nice to have some feedback.