PyxGrant / Platform

Discover, decide, approve, contain, prove.

PyxGrant is one Go binary that sits in front of the calls your agents make: tools, models, other agents, browsers, and payments. It decides each call before it runs, holds the risky ones for a person, and writes a signed, hash-chained record of every decision.

one call, five stagesfrom the demo
  1. Discover
  2. Decide
  3. Approve
  4. Contain
  5. Prove
Architecture

Agents on the left, systems on the right, one decision in the middle.

Callers

Claude Code and Cursor
MCP clients
Your own agents
Apps calling a model API
Peer agents over A2A
Agentic browsers

PyxGrant

ProxiesMCP over stdio or HTTP, model API, A2A, AG-UI
Hook and decision serviceClaude Code, Cursor, and your code over loopback
Decision engineyour policy file, errors refuse
Approval queuesigned decisions, timeout refuses
Audit loghash-chained, sealed with Ed25519

Systems

MCP tool servers
Model providers
Other agents
The person in the chat
Websites
Payment rails and plant controllers
Discover

Find the agents nobody registered.

Read-only scans of each machine list the coding agents, the MCP servers they load, and plaintext secrets in their configs. Exports from your proxy, IdP, and SaaS tenants fill in the rest.

On the machine. agents scan finds Claude Code, Codex, Gemini, Copilot, Cursor, and Windsurf. discover flags MCP servers not routed through PyxGrant, and local model ports (Ollama, LM Studio, vLLM-style) with no gateway in front.
Running now. processes lists agent and MCP processes and whether each is behind a gateway, including ones started outside any config.
Shadow AI. shadow ingest classifies proxy, DNS, extension, process, and OAuth signals: sanctioned, shadow, personal tenant, or imitation.
pyxgrant demo · section 18shadow AI
sanctioned       enterprise ChatGPT
personal-tenant  chatgpt.com
shadow           meeting notetaker (Fireflies)
imitation        lookalike host
shadow           browser extension (Grammarly)
found            local model (Ollama), by process

4 signal families seen · 6 of 6 checks pass
Decide

One decision per call, made before it runs.

Each call is checked against your policy file: who is asking, which tool, what the arguments would do, and what the session has already read. The answer is allow, allow with redactions, hold for a person, or refuse. If the engine can't decide, it refuses.

Blast radius. A recursive wipe or a DELETE with no WHERE is scored and stopped before it reaches the server.
Session taint. Once a session reads HR data, that data can't leave through a public tool. Unrelated content still can.
Tool pinning. A tool that shadows another, or whose description changes after approval, is quarantined and hidden from the model.
Stream hold. A restricted or irreversible tool result on SSE is buffered until the verdict. A deny releases no bytes.
pyxgrant demo · section 11blast radius
tool      hostile/db_query
score     critical, 85 (limit 70)
because   DELETE/UPDATE with no WHERE clause
          targets a high-sensitivity resource
          identity read high-sensitivity data
          this session
decision  BLOCK before execution (-32018)
Approve

Risky calls wait for a person, and silence means no.

A held tool call, model request, agent message, or browser step waits in one queue. An approver signs the decision with their own Ed25519 key. If nobody answers in ten minutes, the call is refused.

Signed approvals. Once approver keys are set, an unsigned or wrong-key decision is refused. Until then, approvals are refused, not waved through.
No self-approval. The agent's own principal can't approve its call unless you turn that on.
Same bytes. What runs is re-hashed against what was approved, so a swapped call is refused.
pyxgrant demo · section 7held
HOLD hostile/delete_record
     awaiting approval 8612106e1424

$ pyxgrant approvals
$ pyxgrant approve 8612106e1424
approved, then run
undo restore record rec-9 from snapshot
Contain

Freeze, resume, revoke, or contain with two people.

Freeze pauses calls in flight and holds new ones until you resume. It can cover every session, one session, a workflow run, a grant, or a whole class of action such as payments or sending, while read-only work carries on.

Revoke. Revoking a grant ends every child grant and every session bound to it, and signs a receipt you can verify offline.
Dual-control stop. contain act records pause and isolate with a 15-minute undo. Panic and kill_fleet need a second, different operator on -confirm, and they kill the target grant on the store, the revocation file, and the signed death stream.
From the console. Freeze a reporting host by hand, or automatically when its risk grade reaches a level you set. Resume is always manual.
containmentpyxgrant
$ pyxgrant freeze                 every session
$ pyxgrant freeze -class pay      payments only
$ pyxgrant contain act -verb pause -actor ops
$ pyxgrant contain act -verb panic -actor ops -confirm sec -target g_9ec3…
$ pyxgrant grant revoke g_9ec3…
  2 grants killed · GrantDead receipt signed
Prove

A record that holds up without trusting us.

Each decision is written to a hash-chained log, and the chain head is sealed with Ed25519. No plaintext secret is written to it. Anyone with the public key can verify the chain and individual receipts offline.

Search it. ediscovery searches by person, session, tool, or decision, and places legal holds.
Account for it. disclosures lists every record where PHI, PII, or a secret was found, and whether it was sent, redacted, or refused.
Keep the key apart. If the signing key sits beside the log, a local admin could shorten and re-sign it. PyxGrant warns when it does. prove -anchor must live in a tree that does not overlap the pack.

Read the trust page →

pyxgrant demo · section 26audit
PASS hash-chained audit log verifies
     39 records, head aec71ae40f85fb02
PASS Ed25519 seal over the chain head verifies
PASS no plaintext secret written to the log

$ pyxgrant audit verify
The console

What the security owner sees.

These are screenshots of pyxgrant console, taken on a test machine while an agent's calls were waiting. Three calls are held for a person, each bound to the exact payload it will run with. Every row carries a signed receipt.

The PyxGrant console: three pending approvals for refund_payment, delete_record, and run_command, the identity registry, and counts of calls inspected, blocked, held, modified, and redacted.
The console's activity log: held calls awaiting human approval with their timeouts and bound payload hashes, one call refused after its approval was aborted, each marked signed.
A held call that loses its caller is refused, not run. That is the "approval-aborted" row.
Coverage

Mapped to OWASP, including the gaps.

This is the product's own map, printed by pyxgrant compliance. It marks what a runtime gateway covers, what it covers in part, and what sits outside it.

LLM Top 10 · 5 covered

Prompt injectionLLM01results
Sensitive disclosureLLM02redact
Output handlingLLM05sanitise
Excessive agencyLLM06hold
Unbounded consumptionLLM10budget

LLM Top 10 · partial or none

Supply chain: tools, not weightsLLM03partial
System prompt leakageLLM07partial
Data and model poisoningLLM04none
Vector and embeddingLLM08none
MisinformationLLM09none

Agentic Top 10 · 8 covered

Goal hijackASI01covered
Tool misuseASI02covered
Identity abuseASI03covered
Supply chainASI04covered
Unexpected code execASI05covered
Memory poisoningASI06covered
Human-agent trustASI09covered
Rogue agentsASI10covered

Agentic Top 10 · 2 partial

Inter-agent communicationASI07partial
Cascading failuresASI08partial
MCP and A2A are proxied and can use mTLS. QUIC and DoH are mapped, not intercepted. Cascades are bounded and can be frozen; a full pipeline graph is not.

The full map, with NIST and the EU AI Act →

Run it on your own machines.

One Go binary, your policy file, and no vendor cloud in the decision path.