Skip to content

Add magpie-model-watch: gateway hook reporting model calls to a local collector - #1192

Open
cpufreestyle wants to merge 1 commit into
magpie-community:mainfrom
cpufreestyle:add-model-watch
Open

cpufreestyle wants to merge 1 commit into
magpie-community:mainfrom
cpufreestyle:add-model-watch

Conversation

@cpufreestyle

Copy link
Copy Markdown

What

magpie-model-watch — a gateway hook that reports each real model call to a collector you run locally: the model, the HTTP status and the latency. A dashboard then shows which models actually answered and how fast, without sending test requests of its own.

Prompt, replies and keys stay put: only the model name, status and timing leave the hook, and every send is a best-effort, fire-and-forget POST that never blocks or fails a request.

Why it is not in packages/

Maintained in its own repository, like magpie-search-mix, @guotree/magpie-websearch and @openviking/magpie-plugin: https://github.com/cpufreestyle/magpie-model-watch

  • npm: magpie-model-watch (0.1.0, MIT)
  • "magpie": { "hooks": "./model-watch.hooks.js", "options": { "bridgeUrl": "http://127.0.0.1:8787", "sampleEvery": 1, "maxPerMinute": 120 } }
  • exports async onRequest(body, ctx) (keeps the model asked for) and onResponse(reply, ctx) (status and latency), plus onEvent for quota/error notices
  • 5 tests (node --test) covering the report shape, throttling, the off-switch and a collector that is not listening
magpie plugin add magpie-model-watch

Note on the collector

The hook needs a collector to be useful; with none listening it does nothing (the POST fails quietly, nothing is retried or logged). Any HTTP endpoint accepting POST /probe/report with {"model","status","latencyMs","source":"hook"} works, so it is not tied to my own dashboard. That is stated in the package README and in the registry summary.

Checks

  • node --input-type=module -e 'registryProblems(...)' on the changed registry.json: 0 problems
  • node --test in the package: 5 pass

@yetone

yetone commented Nov 15, 2026

Copy link
Copy Markdown
Contributor

Thanks. I read model-watch.hooks.js (repo main, same as npm 0.1.0) against magpie's hook host (internal/plugin/host.js, gatewayBegin / gatewayFinish). Several things don't match what the PR and the registry summary say, so I can't list it as it is yet:

  1. The model can belong to another request. _capturedBody is one module-level variable. With two requests in flight (an agent and a subagent, say), request A's onResponse reports request B's model. magpie hands the same ctx object to onRequest and onResponse of one exchange, so keep the model there instead: ctx.state.model = body.model in onRequest, then read ctx.state.model in onResponse.
  2. It holds a whole prompt in memory. _capturedBody keeps the last request body (messages, tool results and all) for the life of the host. The summary says no prompts leave the hook, and they don't, but there's no reason to keep one around. Store only the model string.
  3. No latency is sent. Both the PR body and the summary say "status and latency", but the payload is {model, code, status, source}. Nothing is timed. Record performance.now() in ctx.state in onRequest and send the difference.
  4. The status code is mostly made up. magpie's ctx has no status / statusCode. In onResponse it has success (boolean) and, where there is one, request. So pickStatus returns 500 for a failure and 200 for everything else, including a reply it couldn't read. Either report ok / error from ctx.success and nothing more, or leave the code out when it isn't known. Don't default to 200.
  5. onEvent is never called. magpie calls onRequest, onResponse and onSignIn. Please drop onEvent and the README text about quota/error events, or rewrite it as onSignIn if that's what you're after.
  6. The token also goes in the URL. post() sends it as a Bearer header and as ?token= in the query. Query strings end up in access logs, so the header alone is enough.
  7. The payload doesn't match the PR description. The PR says the collector receives {"model","status","latencyMs","source":"hook"}; the code sends {"events":[{model, code, status, source}]}. Whoever writes their own collector will go by the description, so make the two agree.

Smaller: node --test passing doesn't cover these, because the tests call the hooks directly, one at a time, with a hand-made ctx. Please add a test that runs two overlapping requests and checks each report names its own model.

The registry entry itself (external package, community: true, the icon URL) looks right. Push the fixes to the package, publish 0.1.1, and update the version here. I'll look again then.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants