---
title: "What is captured"
description: "What the Guardian Platform records about an agent built with the SDK, what it can and can't vouch for, and what stays with you."
source: "Guardian Agent SDK"
---
An agent built with the SDK reaches the Guardian Platform in two ways: its **definition and states**, which say what the agent is, and its **model requests**, which the Agent Gateway records as they pass through. This page says what each holds, what it can vouch for, and what neither records.

## The definition and its states

The definition records the agent's configuration: its models and their settings, prompts, tools, skills, memory, sub-agents, middleware, MCP servers and framework ([Definitions](./definitions.mdx)). Every request carries a signed state naming the agent's key, its definition and, where one made the request, the sub-agent. Guardian shows the definition on the agent's Configuration panel, and its version selector lists the definitions the agent has had.

- **Configuration only.** A definition says what the agent is, not what it did. It doesn't record which steps a run took; the Audit Trail has each model request (below), but not the steps between them.
- **No credentials.** A definition that looks like it holds one is refused before anything is sent, and a field you leave out with `exclude` is recorded as deliberately left out, never with its value.
- **Code by fingerprint.** A tool, a dynamic prompt or other middleware is recorded by its name and, where the SDK can read the function's source, a hash of it, not by what it does at run time. A dynamic prompt is recorded as the function that writes the prompt, never a prompt it rendered.
  - **Decorators of yours** are hashed with the function they wrap, outermost first, since their wrappers run too, when they record what they wrap as `functools.wraps` does. That includes one on a method written in your class, or in a class of yours it inherits from. A decorator that doesn't record what it wraps hides the function it calls, and only the wrapper is hashed.
  - **Other libraries' decorators** are hashed too, so the hash changes with that library's version. LangChain's and Python's aren't, and neither is LangSmith's code (its tracing, such as `@traceable`), which doesn't change what the code does. A decorator built with `wrapt` is hashed by its own code, the function given to `@wrapt.decorator` or a `wrapt` proxy class of yours, and then the function it wraps. `wrapt`'s own classes aren't hashed, so a plain `wrapt` proxy passes for the function it wraps.
  - **Code with no source to read** (made with `exec`, say) leaves a tool, middleware or Deep Agents backend with no hash at all, and a graph node or setting recorded by name, rather than a hash that misses that part.
  - **Not covered:** code or data the function reads (helpers in other modules, configuration files, a database), so changes there don't give a new definition. List the files that matter in `sources`, and their contents are fingerprinted too.
- **Memory by place, not contents.** Instructions the agent can't change are recorded by their files' content ID; the files themselves are stored on the platform, and Guardian shows them. Memory the agent writes as it works is recorded by where it lives and whose it is (shared, per namespace or per thread), never by what's in it.

## Model requests

Every model request goes through the proxy to the Agent Gateway, which records it in the Guardian Platform's [Audit Trail](https://guardian.docs.eqtylab.io/user-guide/gateway-audit-trail/): the full request and response, bodies included, with the agent, its key and the state it was signed with. So the messages your agent sends, including the prompt a dynamic prompt rendered for that call, are recorded there as sent. Guardian hides credential headers when it shows an exchange, and never shows your provider key, but doesn't redact the bodies.

## Not recorded

- **Conversation history and memory, as state.** LangGraph's graph state (`messages`), checkpointers, long-term stores and the files a Deep Agents agent writes as it runs stay with you. (Its skills and the memory it can't change are stored and recorded, as above.) They're not part of the definition, and the framework integrations pass a `checkpointer` or `store` on to the framework without recording it. Two agents with the same definition can still behave differently because of what they've remembered.
- **Model calls that never reach the proxy.** The framework integrations route the models they're given when an agent is made, refuse a model they find but can't route, and check each call they route, but they can't see a model your code builds or looks up as it runs. A client you route yourself with `bind()` goes through the proxy; one you don't, doesn't. A call to the proxy that names no agent is refused when the proxy runs with `--require-agent-header`. A call straight to a provider never reaches the proxy, so only the network can stop it: let the agent reach model providers only through the proxy, with a container's egress rules or a sandbox, such as [OpenShell](https://guardian.docs.eqtylab.io/user-guide/openshell-quickstart/).

## What it can and can't vouch for

- **The configuration is the agent's own report.** The framework integrations build the definition from the agent they make and check each call against parts of it: `create_agent` and Deep Agents check the model, settings, tools and response format, and a hand-built graph its settings and tools ([What each one does](../frameworks/index.mdx#what-each-one-does)). With a model client you call yourself, nothing compares your requests' prompts or tools with the definition, and a bound LangChain chat model checks only its settings: the SDK adds the agent's name and definition to each request, and keeping the two consistent is up to your code. Either way, the Guardian Platform can't inspect your process. A signed state shows which agent's key signed a request and what definition it named, not that the code running matches it beyond the fingerprints it records.
- **The agent header is a local trust boundary.** The proxy only answers callers on its own machine, and signs as whichever enrolled agent a request names. Any process that can reach the proxy can name any agent enrolled on it.
- **Agents on one machine are told apart, not isolated.** Several agents sharing a proxy each sign with their own key and are recorded separately. Nothing stops one of them naming another; run agents that mustn't act as each other on separate machines or containers, each with its own proxy.