Impraint

Core concepts

The mental model behind Guard, traces, steps, the Guard instance and fail-open.

The Guard instance

A Guard represents one agent. Create one instance per agent_id and reuse it across your app. Guard is a singleton per agent_id: creating it again with the same agent_id returns the existing instance and ignores the new arguments.

guard = Guard(api_key="...", agent_id="support-agent")

Besides api_key and agent_id, Guard accepts:

ArgumentPurpose
env"production" (default) or "development"
api_urlOverride the server address, for example for an on-premise deployment
fail_openTrue (default): Guard problems never crash your agent. See Fail-open
scrub_fieldsMetadata field names to redact before anything is sent, for example ["credit_card", "password"]
tagsLabels stamped on every trace, for example {"env": "production"}

Traces and steps

A trace is one run of your agent: one call to a function decorated with @guard.track. A trace contains steps, the individual things that happened during the run. Steps are nested, so each one knows which step it ran inside.

Every step has an action type:

Action typeWhat it represents
llm_callA call to any LLM, with model, tokens and cost
tool_callThe agent calling an external tool or function
http_requestAn outbound HTTP request
agent_callA parent agent calling a sub-agent
graph_nodeA LangGraph node running
retriever_callA retriever lookup (RAG or otherwise)
circuit_breakerA circuit breaker decision, logged automatically
content_safetyA content-safety scan, logged automatically
customAnything else you track with @guard.track

If a tracked function calls another tracked function, the inner call becomes its own trace, linked to the outer one. It is not a step inside the outer trace.

The @guard.track decorator

@guard.track wraps a function and turns each call into a trace. It works on sync and async functions, in two forms:

@guard.track                                   # bare
def run(question): ...

@guard.track(action_type=ActionType.LLM_CALL)  # with options
def run(question): ...

The options are action_type, metadata (extra fields stored on the step) and tags.

Guard also stores a short input summary (the function's arguments) and output summary (its return value). Both are scrubbed of PII and cut to 500 characters. A function with no arguments has an empty input summary, which is expected.

Fail-open

Guard never takes your agent down. fail_open is a single setting on Guard, and it defaults to True. If the Guard service is unreachable, slow, or returns an error, the SDK logs a warning and your function continues as if Guard weren't there.

Set fail_open=False if you would rather raise an error whenever Guard can't be reached. A wrong API key always raises, in either mode.

The same setting decides what happens to actions protected by rules and approvals. With fail_open=True, an action is allowed if Guard cannot check it, so a risky action can run with no approval. For agents that handle risky actions, set fail_open=False.

Cross-agent escalation

When one agent hands work to another (for example a support agent escalating to a specialist), call the second agent's tracked function from inside the first agent's tracked function. Guard links the two traces automatically. You never set a parent id yourself, and each agent keeps its own Guard and agent_id.

On this page