jq.
See the real request
Model ID, messages, tools, and parameters exactly as the agent sent them
Streaming intact
Chunks are forwarded as they arrive, so the agent behaves normally
No dependencies
One file, Node.js 18 or later, nothing to install
How it works
Authorization header, so your API key stays in the agent’s config and every Venice endpoint works through it: /chat/completions, /responses, /models, /embeddings, and the rest. The only change you make to the agent is the base URL.
For each request, the proxy logs:
- The method, path, and request body, with your API key masked to its last four characters
- The response status and body. Streamed responses are stored as a list of parsed chunks.
- Token usage, from the
usageobject Venice returns - Total duration and time to first byte
x-venice-*andx-ratelimit-*response headers, such as remaining balance, rate-limit state, and model deprecation warnings
This is a debugging tool for your own machine. It binds to
127.0.0.1 only, has no authentication of its own, and writes prompts and code to disk in plain text. Don’t deploy it as a shared gateway. If you need one, see Building a Rust LLM Gateway.Prerequisites
- Node.js 18 or later (
node --version) - A Venice API key from venice.ai/settings/api
- A coding agent already working with Venice, such as Claude Code, Codex CLI, OpenCode, Cline, or Aider
jqfor reading the logs (optional, but recommended)
Setup
1
Create the proxy
Save this as There’s a few things worth pointing out here:
venice-debug-proxy.mjs in a scratch directory:venice-debug-proxy.mjs
- Streaming works normally. Each chunk from Venice is written to the agent the moment it arrives, and a copy is kept for the log. The agent sees the same token-by-token stream it would get from Venice directly.
- Compression is handled for you. Node’s
fetchdecompresses the response, so the proxy dropscontent-encodingbefore passing headers on. Otherwise the agent would try to decompress plain text and fail. - Disconnects are passed on. If you cancel a turn in the agent, the proxy aborts the upstream request too, so Venice doesn’t keep generating tokens nobody reads.
2
Start it
PORT or LOG_FILE in the environment to change either default.3
Check it with curl
In a second terminal, send a request through the proxy:The proxy prints one line per request:That’s a lot of prompt tokens for “Say hello”. Most of them are Venice’s default system prompt, which is added to chat requests unless you set
venice_parameters.include_venice_system_prompt to false. This is exactly the kind of thing the proxy makes visible.4
Point your agent at the proxy
In your agent’s Venice settings, replace
https://api.venice.ai with http://127.0.0.1:8787 and keep the rest of the URL as it is. The proxy forwards the full path, so whatever the agent’s guide tells you to enter still works.OpenCode’s bundled Venice provider and Kilo Code’s native Venice provider don’t expose a base URL, so switch to the manual or OpenAI-compatible provider while you debug.In OpenCode, give the debug provider its own ID, such as
venice-debug, and run it with -m venice-debug/<model-id>. If you’ve saved a key with /connect, OpenCode sends that stored key for the venice provider ID even when your config sets apiKey.Use 127.0.0.1 rather than localhost. On some systems localhost resolves to the IPv6 address ::1, which the proxy isn’t listening on.5
Reproduce the problem
Use the agent as you normally would until the problem happens again, then look at the proxy’s terminal output and the log file.
Reading the logs
Each line invenice-debug.jsonl is one complete JSON object, so jq can slice it however you need.
Show the most recent request and response:
What to look for
Without writing any code
If you’d rather click through traffic in a browser, mitmproxy can run as a reverse proxy in front of Venice:http://127.0.0.1:8787/api/v1 the same way, then inspect each request in the mitmweb UI. The Node proxy is easier to script against and keeps a log you can grep later. mitmproxy is better for browsing a session interactively.
Keep the logs private
Venice doesn’t store your prompts or responses for normal inference (see Privacy), but this log file does. It contains your code, prompts, tool output, and model responses in plain text.- Run the proxy outside your project, or add
venice-debug.jsonlto.gitignore. - Delete the log when you’ve finished debugging.
- Don’t paste full log entries into public issues. Pull out the
status,error, and the relevant part ofresponseinstead.
Finishing up
When you’re done, stop the proxy withCtrl+C and switch the agent’s base URL back to https://api.venice.ai/api/v1. If you forget, the agent will fail with a connection error as soon as the proxy isn’t running, which is at least easy to spot.
Thanks for reading! Hopefully the next time an agent says “something went wrong”, you’ll be able to see exactly what went wrong.