Overview
ArgusWatcheris what you interact with. It hooks into your graph, records every node's execution, runs detectors, and produces traces. One watcher per run.
Basic Usage
Three ways to set up. Pick whichever fits your code:
from argus import ArgusWatcher
# Option A — pass graph to constructor (recommended)
watcher = ArgusWatcher(graph)
app = graph.compile()
result = app.invoke(initial_state)
# Option B — separate watch call
watcher = ArgusWatcher()
watcher.watch(graph)
app = graph.compile()
result = app.invoke(initial_state)
# Option C — after compile
watcher = ArgusWatcher()
app = graph.compile(checkpointer=memory)
app = watcher.watch_compiled(app)
result = app.invoke(initial_state)Runs save automatically for linear and fan-out graphs. Cyclic graphs need a manual watcher.finalize() call.
Parameters
Everything is optional. Pass to the constructor to override config file and environment variable values.
graphStateGraphLangGraph graph to monitor. If passed, watch() is called automatically.
Default: None
max_field_sizeintMax characters per captured state field. Fields exceeding this get truncated.
Default: 50_000
strictboolRaise an exception if any detector fires. Use in CI/CD to fail builds on quality regressions.
Default: False
investigatebool | "always"LLM root-cause investigation. True = on failure only, "always" = every node, False = off.
Default: True
redact_keysset[str]Field names to redact from stored outputs (e.g. {"password", "api_key"}).
Default: None
validatorsdictPer-node semantic validators. Use "*" as key to run on every node. Each validator is a (bool, str) callable.
Default: None
# Validators — catch semantic failures
watcher = ArgusWatcher(graph, validators={
"classify": lambda o: (o.get("label") in ["yes", "no"], "unexpected label"),
"*": lambda o: ("error" not in o, "error key present"),
})"*" runs on every node.
persist_stateboolSave run records to .argus/runs/. Set False for ephemeral monitoring.
Default: True
record_httpboolRecord all external HTTP/API calls for deterministic replay.
Default: True
semantic_judgeboolLLM-powered quality judge on every node output. Requires OPENAI_API_KEY.
Default: False
judge_modelstrModel for the semantic judge and investigation.
Default: "gpt-4o"
# Full example with multiple options
watcher = ArgusWatcher(
graph,
semantic_judge=True,
judge_model="gpt-4o-mini",
strict=True,
record_http=True,
redact_keys={"api_key", "token"},
validators={
"summarize": lambda o: (len(o.get("summary", "")) > 10, "Summary too short"),
},
)Cost
semantic_judge sends node outputs to an LLM. This adds API cost proportional to the number of nodes. Use it in staging/CI, not every production run.Lifecycle
A Watcher goes through four phases:
- Created — constructor called, parameters loaded
- Watching — graph instrumented, ready for execution
- Recording — pipeline running, capturing node data
- Finalized — detectors run, forensics generated, trace stored
Single-use
watch() on a finalized Watcher raises WatcherStateError.