Recording a nanobot session and replaying it offline — plus two config gotchas #5753
xizhuomengcontin
started this conversation in
Show and tell
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
I record agent runs for a living (I maintain OrcaReplay, Apache-2.0), so I spent this evening finding out whether nanobot can be captured and replayed. It can — but not the way it works for most frameworks, and the reason is specific enough to nanobot that it seemed worth writing down here rather than in my own docs.
The finding: nanobot pins its origin in config, so environment variables do not reach it
Most Python agent frameworks end up at
AsyncOpenAI()with no arguments, which readsOPENAI_BASE_URLfrom the environment. That makes out-of-process capture trivial: launch the agent with that variable pointed at a local proxy and you are done.nanobot does not do that. In
providers/openai_compat_provider.pythe client is built as:and
_effective_basecomes from the provider spec inconfig.json.OPENAI_BASE_URLappears nowhere in the package — I grepped. So the usual trick is a no-op here, which is a reasonable design (explicit config beats ambient environment) but means a recorder has to meet nanobot where it actually looks.The answer is to give nanobot a provider that points at the recorder, which your
providers.customslot already supports.What actually worked
1. Start a recording proxy that nanobot can be pointed at.
2. Point a custom provider at it.
{ "providers": { "custom": { "api_key": "your-real-key", "api_base": "http://127.0.0.1:53581/v1" } }, "agents": { "defaults": { "model": "custom/your-model", "provider": "custom" } } }3. Run nanobot normally. Your key is unchanged — the proxy forwards it upstream.
4. Replay it with the provider gone.
orca attach --replay run_bb6a05db3d7a # info attached ... serving=run_bb6a05db3d7a exchanges=1 egress=blockedRepoint
api_baseat the new port, run the same command, and nanobot produces the same answer with the upstream process killed — I verified that by terminating the origin first, then running nanobot again and watching it still answer. No provider is contacted and no tokens are spent; nanobot's own loop, tools and session handling run for real.Being precise about the evidence: I stopped the replay proxy with a process kill rather than ctrl-C, so I do not have its closing verdict line — what I can state is that the origin was dead and the recorded answer still came back.
Two config gotchas that cost me ten minutes
Both are pydantic validation errors that are clear once you read them, but neither is obvious from the outside:
api_typeaccepts onlyauto/chat_completions/responses—"openai"is rejected.api_typeis only accepted underproviders.openai. Setting it onproviders.customfails with "providers.<name>.api_type is only supported for providers.openai", even thoughcustomhas the field in its schema. Leaving it unset works fine andautodoes the right thing.If that restriction is deliberate, it might be worth dropping the field from the non-
openaiprovider models so the schema stops advertising something it rejects. Happy to open an issue if that is useful rather than known.Why anyone would want this
A recorded run is a session you can hand to someone else. A nanobot bug that only shows up on the fourth tool iteration becomes something a maintainer can reproduce without your API key and without spending anything, and the same recording works as a regression test in CI.
Two limits I would rather state than have someone discover:
egress=blockedmeans model-provider egress, not network isolation. Replay stops the model call, but nanobot's own tools still run for real — a web tool that fetched a URL fetches it again. It is not a sandbox.Tested against
nanobot-ai0.3.0 on Python 3.12, with a deterministic local origin standing in for a provider.All reactions