---
title: "Definitions"
description: "What an agent's definition records, how it gets a content ID, and how it becomes the signed state of every request the agent makes."
source: "Guardian Agent SDK"
---
An agent's **definition** is what the agent is: its models and the settings it calls them with, its prompts, its tools, its skills and memory, its sub-agents, and the code that shapes its behaviour. The SDK builds it from your code, the local Viper proxy registers it, and every request the agent makes is signed with it.

## What a definition records

| Part        | What's recorded                                                                                                                                                 |
| ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Models      | Each model's provider and name, in fallback order, with the settings that change its answers (temperature, reasoning effort). Never a client's keys or headers. |
| Prompts     | The system and developer prompts, in order.                                                                                                                     |
| Tools       | Each tool's name, description and input schema, as the model sees them, and for a Python function, a hash of its code.                                          |
| Skills      | Each skill's files, stored on the proxy and recorded by content ID.                                                                                             |
| Memory      | Instructions the agent reads but can't change, by their files' content ID; memory it writes as it works, by where it lives and whose it is, never its contents. |
| Sub-agents  | Agents declared inside this one, each with a definition of its own.                                                                                             |
| Middleware  | The code that runs around model calls, in the order it runs, with its settings, and a hash of its code where the SDK reads it from your agent.                  |
| MCP servers | Each server the agent uses: its name, transport and address or command.                                                                                         |
| Framework   | What the agent is built with, and the package versions that matter.                                                                                             |
| Graph       | Its nodes and the edges between them, for a graph-shaped agent.                                                                                                 |
| Also        | A description, your own version label, declared permissions and guardrails, source files to fingerprint, and framework-specific extensions.                     |

The [framework integrations](../frameworks/index.mdx) (LangChain's `create_agent`, Deep Agents, hand-built LangGraph graphs) build the definition from the agent they make. For anything else, you describe it with `ga.Definition`, or the same arguments to `guardian.agent()`. [Describe an agent](../guides/describe-an-agent.mdx) and [Definition fields](../guides/definition-fields.mdx) cover every field, and the [Definition](../api/definition.mdx) reference lists every argument.

`definition.document(name)` shows exactly what the proxy will receive:

{/* generated file sdks/python/snippets/show_definition.py python */}

```python
import json

import guardian_agent as ga

definition = ga.Definition(
    description="Answers questions from the internal docs.",
    model=ga.Model("openai", "gpt-4.1", temperature=0),
    instructions="You research questions using the internal docs.",
)

# What the proxy receives for an agent named "researcher"; nothing is sent here
print(json.dumps(definition.document("researcher"), indent=2))
```

{/* end generated */}

It prints the definition as JSON, under the schema `viper/agent-definition/v1`, with the agent's name, description and framework (`custom`, here), its model with its `temperature` setting, and its system prompt. Nothing is sent to make it.

## Checked where you make it

A definition is checked the moment it's created, against the definition schema and the rules the proxy applies on top of it, so a mistake fails at the line that made it, naming each problem by its path. The proxy still has the last word, and checks sizes itself when the definition is registered.

It's also scanned for credentials, the way the proxy scans it: a definition is stored, signed and shown to reviewers, so one that looks like it holds an API key, a token, a private key or a credential in an MCP server's address is refused before anything is sent. The error names where, never the value. To leave a field out on purpose, name it in `exclude`; the definition then records that it was left out.

## Content IDs

Each definition has a **content ID**, a hash of its canonical JSON, such as `baga6yaq6e...`. The proxy computes it when it registers the definition; the SDK never computes one. Lists whose order means nothing, such as tools and skills, are sorted first, so the same agent always gives the same content ID, and any change to what's recorded (a prompt, a setting, a tool's code, a package version) gives a new one.

`agent.register()` returns it, and `agent.definition_cid` holds it once the agent is registered. Prompts over 16 KiB are stored apart and referred to by their own content ID.

## From definition to signed state

On the agent's first request, the SDK registers its definition with the proxy, once, and again after the proxy restarts. From then on, each request names the agent and its definition, and the proxy signs it with a **state**: a signed snapshot that ties the agent's key to its definition's content ID, and to the sub-agent that made the request, if one did. The Guardian Platform checks each state as the request passes through, and keeps it.

The proxy signs a new state for an unchanged definition when it restarts, and every few minutes. In Guardian, an agent's Configuration panel lists one entry per definition, however many states named it, so you see when the agent changed, not each renewal.

The Guardian Platform also derives the agent's configuration from its definition: the models, prompts, tools, skills, memory and MCP servers that assessments judge the agent on.

### Viper's state isn't your graph's state

In Viper and the Guardian Platform, an agent's **state** means its identity and its configuration: who it is and what it is made of. It isn't LangGraph's graph state (the messages of a conversation and what a run keeps between steps), which is never part of a definition or a state. [What is captured](./what-is-captured.mdx) says what is recorded, and where.