Panoptes
Agent observability, local audit trails, and policy gates.
A local-first view of OpenAI-, Anthropic-, Gemini-, and Hermes-based workflows.
Panoptes gives AI-agent traffic one place to land. Point a supported model client at the local reverse proxy and Panoptes turns requests, responses, tool instructions, policy decisions, and cost data into a queryable SQLite audit trail. Hermes integrations can also report lifecycle events and ask Panoptes for a synchronous pre-tool decision.
Panoptes runs locally with no external service. It records model API traffic and host-reported lifecycle events; tool calls emitted by a model remain requests unless the host reports an execution outcome.
Why
Agent logs tend to be provider-specific, short-lived, and hard to compare. Panoptes is built to answer a smaller set of operational questions well:
- Which model requests and tool instructions crossed the controlled API path?
- Which tool requests did a native adapter authorize or deny?
- Which policy snapshot informed each recorded authorization decision or violation?
- Has the locally stored event history changed since a checkpoint?
Every supported adapter writes the same event shape. Every event carries capture metadata describing where it came from and how strong that observation is. That gives you one dependable record for tracing agent behavior, reviewing policy decisions, investigating incidents, and testing ideas—without the operational weight of a distributed observability stack.
Quick Start
Install Panoptes as an isolated command-line application:
pipx install panoptes-observe
Or use uv:
uv tool install panoptes-observe
The distribution is named panoptes-observe; the installed command remains
panoptes. To work on the source instead:
git clone https://github.com/miggy-code/Panoptes.git
cd Panoptes
python -m pip install -e ".[dev]"
Capture model API traffic
Start Panoptes in one terminal:
panoptes proxy --port 8081
Then point a supported client at it from another terminal:
ANTHROPIC_BASE_URL=http://127.0.0.1:8081 claude
After the run, inspect what Panoptes recorded:
panoptes status
panoptes query --event-type tool_call --limit 10
Observation is fail-open by default. For enforcement, provide a valid policy
directory and choose fail_closed explicitly:
panoptes proxy \
--port 8081 \
--policies-dir ~/.panoptes/policies \
--policy-failure-mode fail_closed
The proxy only binds to loopback. Client sockets have a 30-second I/O timeout
and the server accepts at most 64 concurrent requests by default; tune these
with --client-timeout and --max-concurrent-requests.
Install Hermes lifecycle hooks
python -m panoptes.install_hermes_plugin
The installer adds lifecycle hooks for agent:start, agent:step, and
agent:end. Those hooks observe; they do not block. Local tool enforcement
requires the Hermes host to call authorize_tool_call() synchronously and
honor allowed=False. In fail_closed mode, an authorization whose evidence
cannot be stored is denied.
Query and verify
panoptes query --agent hermes --event-type agent_step --limit 50
panoptes query --agent hermes --event-type decision_point --limit 50
panoptes session <session-id>
panoptes evidence <event-id>
# Verify local hash links and export a checkpoint for separate storage
panoptes verify
panoptes checkpoint > checkpoint.json
# Later, prove that separately stored checkpoint is a prefix of current history
panoptes verify --checkpoint checkpoint.json
Read-only database commands require an existing initialized audit database. A
missing, mistyped, or empty --db-path exits with status 2 instead of creating
a new database.
Architecture
Enforcement plane: adapter → normalize → policy gate → model/API boundary
│
Audit plane: adapter → normalized event → SQLite → CLI
The design has two intentionally small paths. The enforcement path makes a
decision before a controlled boundary. The audit path commits normalized
evidence to SQLite and keeps it available through the CLI. capture.py
describes each adapter's fidelity so consumers can distinguish a model
instruction from a host-reported or pre-authorized action.
Capture adapters
| Adapter | Observes | Enforcement boundary |
|---|---|---|
| Reverse proxy | Supported model requests, responses, tool instructions, and client-reported tool results | Request preflight and fully buffered model responses |
| Hermes plugin | Host-reported agent_start, agent_step, and agent_end events |
Optional host-callable pre-tool authorizer, recorded as decision_point |
The reverse proxy is a real boundary only for traffic that crosses it. It cannot see an arbitrary local file read after the agent receives a response, and an agent can bypass it if it still holds provider credentials. Stronger deployments must isolate those credentials and block direct provider egress. At the boundary itself, Panoptes rejects ambiguous JSON instead of guessing which duplicate value should inform a policy decision.
For reliable cross-request timelines, adapters should send
X-Panoptes-Session: <stable-session-id>. Without it, each exchange is
isolated. X-Panoptes-Agent and session headers are client assertions, not
authenticated workload identities, and are removed before upstream forwarding.
Audit schema
{
"event_id": "uuid",
"timestamp": "2026-07-17T14:30:00.000Z",
"agent": {
"type": "claude_code",
"session_id": "abc123",
"run_id": "run456"
},
"event_type": "tool_call",
"action": {
"tool_name": "terminal",
"parameters": {"command": "kubectl get pods -n prod"},
"data_accessed": ["infra", "prod"]
},
"outcome": {
"status": "pending",
"summary": "Model proposed this tool call; local execution was not observed"
},
"context": {
"turn_number": 12,
"capture": {
"adapter": "http_proxy",
"observation_boundary": "model_api",
"execution_observed": false
}
},
"cost": {"tokens_in": 800, "tokens_out": 150}
}
Before an event reaches disk, Panoptes validates its identifiers, timestamps, outcomes, and costs; redacts common secret forms; and derives heuristic data-access tags from the action. Those tags are useful inputs for local policy and investigation, but they can be wrong. Treat both redaction and classification as defense in depth, not as complete data-loss prevention.
Request events include complete bounded summaries of requested client-side,
provider-hosted, and unknown tool capabilities. Client-executed model tool
proposals remain pending; recognized provider-hosted actions record whether
they completed, failed, or remain pending upstream. Hosted result excerpts are
redacted and bounded. Unknown requested tool types are denied in
fail_closed; fail_open records and logs a warning.
Policy engine
Policies are YAML files in ~/.panoptes/policies/:
name: "no-prod-access"
description: "Block tool calls classified as production access"
enabled: true
scope:
agents: ["*"]
rule:
event_type: "tool_call"
conditions:
- field: "action.data_accessed"
operator: "contains"
value: "prod"
logic: "AND"
action: block
message: "Production access blocked. Request approval first."
- Operators:
==,!=,contains,in,matches,gt,lt,gte,lte - Logic:
AND/OR - Scopes: agent and session
- Actions:
allow,warn,block - Loading: one validated, content-digested policy set at startup; restart the proxy after changing policy files
- Failure posture: explicit
fail_openorfail_closed
Policies are strict on purpose. Unknown fields, malformed conditions, duplicate YAML keys, an empty directory, or any invalid file make the set fail to load. That turns a typo into a visible startup problem instead of a silently weaker rule.
Supported Protocols and Adapters
| Protocol / adapter | Capture method | Boundary |
|---|---|---|
| Anthropic Messages API | Reverse proxy | Model API |
| OpenAI Chat Completions and Responses APIs | Reverse proxy | Model API |
Gemini generateContent and streamGenerateContent |
Reverse proxy | Model API |
| Hermes Agent | Native plugin | Host-reported lifecycle; optional pre-tool authorization |
An agent is proxy-compatible only if it lets you replace its model API base URL and emits a supported protocol. That is not equivalent to a tested native integration.
Current action parsing covers OpenAI function/custom/computer/shell/apply-patch
and hosted-tool output items, Anthropic client and server tool blocks, and
Gemini function, built-in tool, and code-execution parts. Unknown tool
declarations or response item types never become an implicit safe result:
fail_closed denies them, while fail_open records degraded inspection.
Provider features introduced after this release, including OpenAI programmatic
tool-calling output, require an adapter update and adversarial fixtures before
they are supported.
Commands
panoptes proxy Start the loopback-only model-API reverse proxy
panoptes --version Show the installed Panoptes version
panoptes status Show event statistics
panoptes query Query events by agent, type, tool, or time
panoptes session <id> Show up to 10,000 newest session events
panoptes evidence <id> Reconstruct a related decision path
panoptes verify Verify the local chain or a separately stored checkpoint
panoptes checkpoint Print the current chain checkpoint
panoptes policy list List the active policy snapshot
panoptes policy add Add a policy file
panoptes policy check Scan a bounded newest-event selection; errors exit nonzero
panoptes policy test Test one policy against one event
Project Status
| Component | Status |
|---|---|
| Model-API reverse proxy | Alpha |
| Hermes lifecycle plugin and authorizer API | Alpha |
| SQLite storage and local hash chain | Available; external checkpoints remain operator-managed |
| Query, policy, and integrity CLI | Available |
| YAML policy engine | Alpha |
| Mandatory local execution broker | Out of scope today |
The project targets Python 3.10 through 3.13 and runs its tests, distribution validation, and wheel smoke test in GitHub Actions. Passing tests do not expand the adapter guarantees described in SECURITY.md.
Runtime dependencies are intentionally small: httpx and PyYAML.
Development
Create an environment, install the development extra, and run the suite:
python -m venv .venv
source .venv/bin/activate
python -m pip install -e ".[dev,release]"
python -m pytest -q
python -m build
python -m twine check --strict dist/*
The tests are local and network-independent. A change is ready to review when
the full suite passes and git diff --check is clean. Release ownership and
the tagged publishing flow are documented in RELEASING.md.
Contributing
Bug reports, protocol fixtures, and focused adapters are welcome. The most useful contributions strengthen an existing boundary: native pre-execution adapters, external append-only audit sinks, signed policy distribution, and adversarial provider fixtures. For security issues, please use the private reporting path in SECURITY.md.
License
Apache 2.0 — see LICENSE.
Metadata
Release files for panoptes-observe 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| panoptes_observe-0.1.0.tar.gz | 160.4 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| panoptes_observe-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 268.3 kB
Release files / panoptes_observe-0.1.0.tar.gz
| Download URL | panoptes_observe-0.1.0.tar.gz |
|---|---|
| Size | 160.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
893bd622b4d65490484ec9e770e23707491f30ec8bf9dca5f6222d92a53e1dd1
|
|
BLAKE2b-256 checksum How to use checksums |
0e1cd168416f9d0aac88c13688039dd8d8c57ef18401dedf0dee5a761eb3480b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 21, 2026.
Transparency logRelease files / panoptes_observe-0.1.0-py3-none-any.whl
| Download URL | panoptes_observe-0.1.0-py3-none-any.whl |
|---|---|
| Size | 107.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
206fa436f12da3a5f7e8e61fe34a163a865158d98d7c2ccd8d3e91b8737e40ef
|
|
BLAKE2b-256 checksum How to use checksums |
fd6f6ef0d0b7b99f597f97cc31128bd5f54f5283e3452dde00a9dcd39cda4e8c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 21, 2026.
Transparency logSecurity for panoptes-observe 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for panoptes_observe-0.1.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 21, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.