Repository navigation
feat(gateway): trigger events name the provoking call's arguments - #486
Merged
Merged
Conversation
A detected or cancelled event recorded only the tool and role of the call that provoked it, so finding which call missed or matched a trigger meant replaying the solver's trajectory against the trigger's rules. The event now carries the call's args, echoed as mirrors' args already are: id and metadata values pass, every other value is a shape. An echo past 4 KB, or too deep to build, is recorded as the args' shape alone, since detection is fail-open and a raise would skip every trigger the call provokes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s echo
The gateway refuses a tool call whose args nest past a few hundred levels ("Circular reference detected (depth
exceeded)") before the trigger engine sees it, so the echo can't recurse anywhere near Python's limit.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…n they hold too many values Building the echo of a 10k-row argument only to measure it and throw it away doubled that call's time. A count that stops at 256 values now decides first, so large args are shaped without the copy. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Collaborator
Author
|
@greptileai review |
…s args reach its event Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… echo rules The limits and their two helpers now sit beside `_ECHO_VALUE_MAX` and `_echo_args`, named as a pair (`_ECHO_ARGS_MAX_CHARS`, `_ECHO_ARGS_MAX_VALUES`). `_echo_args`'s docstring is back to describing mirrors, and a comment by the event vocabulary names the three forms `provoking` takes. No behaviour change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A trigger's
detectedandcancelledevents record the call that provoked them asprovoking: {tool, role}. That says which tool set a trigger off, but not what the call said. So to find out why a trigger did or didn't match, you had to replay the agent's trajectory against the trigger'swhererules. A common case: a DM addressed by conversation id when the trigger expects a user id.provokingnow also carries the call'sargs, echoed the same way a mirror action's args already are inaction_ok:id/Id/_id, plus the existing allowlist);{"redacted": {"type": "str", "len": 120}}, so message bodies and addresses stay out of the log.{"kind": "detected", "trigger_id": "dm", "provoking": {"tool": "slack_send_message", "role": "default", "args": {"channel_id": "D0ACC8C6C66", "message": {"redacted": {"type": "str", "len": 84}}}}}Three kinds of event share the dict and so gain
args:detectedfor action triggers;cancelled, naming the call that cancelled a deadline;detectedfor state triggers re-checked after a call.Website (
source: website) and clock (source: clock) provoking are unchanged.Size bound. The agent controls these arguments. The log keeps up to 10,000 events, and every event is also logged at info. So args holding more than 256 values, or whose echo passes 4 KB of JSON, are recorded as their shape alone (
{"redacted": {"type": "dict", "len": N}}). The value count runs first and stops at 256, so a large argument is shaped without building its echo: 0.7 µs for a 10k-row argument, and 3.4 µs to echo a Slack-sized{channel_id, message}.Compatibility
The change is additive. The explorer UI and the verifiers'
run_contextread onlytool/role, or passprovokingthrough. A step talking to an older gateway simply sees noargs, so no card feature is needed.Testing
tst/unit/env/gatewayplusrun_context, 780 passed. Two tests are new:RegisterEnvTriggersStep./step.GET /triggers/stateshowedargson the actiondetected,cancelledand statedetectedevents.item_idwas echoed, while bodies were redacted and absent from the log.gateway_test.py(integration-local-gateway) andtest_register_env_triggers_local.pyon the same VM: 32/32 passed._idkey all come out as shapes, and none of them appears anywhere in/triggers/state. A nestedfile_idis echoed.repeattrigger give 50 detections, each carrying its own call'sitem_id, with none missing or duplicated. p50 latency under that load matches main (about 178 ms on both).🤖 Generated with Claude Code


Confidence Score: 5/5
The PR appears safe to merge; no new actionable issues were found.Summary
Trigger events now include a redacted copy of the call's arguments.
Reviews (5) · Last reviewed commit: "refactor(gateway): keep a provoking call..." · Reviewed by Greptile