An OpenAI-compatible chat completions server that logs harness traffic (dumb or MITM).
Project description
Undercover Agent
A drop-in OpenAI-compatible chat completions server that sits between a coding harness (GitHub Copilot, OpenCode, or anything that speaks the OpenAI API) and a real model — and logs everything that flows through it.
Point your harness's "OpenAI base URL" at Undercover Agent, and every request and response is recorded into clean, browsable, per-conversation logs.
What it's for
When you're building or debugging an agent, the most useful thing you can have is the exact traffic the harness sends to the model: the full message history, system prompts, declared tools, sampling params, and the responses. Undercover Agent captures all of it without requiring any changes to the harness beyond a base-URL swap.
Two modes
- Dumb mode (default) — never contacts a real model. It returns well-formed,
intentionally boring canned responses (correct
choices,finish_reason, a plausible fakedusageblock) so the harness keeps working while you inspect what it's sending. - MITM mode — forwards each request to a real upstream LLM via the official OpenAI SDK, relays the answer back unchanged, and logs everything in between.
Both modes stream when the request asks for it (stream: true), passing SSE
through transparently.
Sessions
The OpenAI chat API is stateless — every request resends the whole conversation
and carries no session id. Undercover Agent reconstructs sessions by prefix
matching: if a stored conversation is a prefix of an incoming request's
messages, the request is treated as a continuation of that session (longest
match wins); otherwise a new session is born.
Each session gets a timestamped id like 20260630T101345Z-a1b2c3d4, so logs sort
chronologically and any session can be opened directly by its id.
Install & run
Requires Python 3.9+.
pip install undercover-agent
Or, from a checkout of this repository:
pip install -r requirements.txt
Dumb mode (default)
python -m undercover_agent
Then point your harness at http://localhost:8000/v1.
MITM mode
python -m undercover_agent --mode mitm \
--base-url https://api.openai.com/v1 \
--api-key sk-...
The harness's own Authorization header is logged but never forwarded — Undercover
Agent authenticates upstream with the --api-key you pass here.
CLI flags
| Flag | Default | Description |
|---|---|---|
--mode {dumb,mitm} |
dumb |
Logging-only or forward-upstream. |
--host |
0.0.0.0 |
Bind address. |
--port |
8000 |
Bind port. |
--model |
undercover-agent |
Model id advertised to the harness. |
--logs-dir |
logs |
Where per-session JSON logs are written. |
--base-url |
— | Upstream base URL (MITM only). |
--api-key |
— | Upstream credential (MITM only). |
HTTP API
Undercover Agent implements the slice of the OpenAI REST API that harnesses actually use:
POST /v1/chat/completions— the main endpoint (streaming and non-streaming).GET /v1/models— returns the advertised model id(s).GET /health— liveness check.
Viewing the logs
Logs are written as one JSON file per session under logs/<session-id>.json. That
JSON is the machine-readable report. There's also a human-readable HTML view,
available two ways:
Live, while the server runs
GET /— index of all sessions, newest first (timestamp, mode, model, turn count, token usage).GET /sessions/<session-id>— the full conversation rendered like a normal chat UI.GET /sessions/<session-id>.json— the raw JSON log.
Static export
python -m undercover_agent report
Writes reports/index.html plus one reports/<session-id>.html per session. Open
reports/index.html and click through, or open a session file directly.
How it's built
- Flask for the HTTP server (streaming via generator responses).
- openai — the official SDK, used to forward requests upstream in MITM mode.
Entrypoint is python -m undercover_agent.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file undercover_agent-0.1.0.tar.gz.
File metadata
- Download URL: undercover_agent-0.1.0.tar.gz
- Upload date:
- Size: 22.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2e115c6a9bb4d375c4c5f3820b78b4fb7ce464030c8ccf02c4db398d9f059ee4
|
|
| MD5 |
625e7a54d97520c2dc676c5339b784da
|
|
| BLAKE2b-256 |
afa88446a39b4ed7400f6122378f9f3d496d2d3fb7cc6619641fec73df7664fe
|
File details
Details for the file undercover_agent-0.1.0-py3-none-any.whl.
File metadata
- Download URL: undercover_agent-0.1.0-py3-none-any.whl
- Upload date:
- Size: 24.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e0380bbdbafac6b21ac17124675835b5aeff8669bf2194c3588782538ec29802
|
|
| MD5 |
b3bea5c8a39b511dde1face3c3d45bb3
|
|
| BLAKE2b-256 |
4e4346662010e6a9bc2123fb0cd9928bcca3860900aae06e1e9ac202999a9d76
|