Skip to content

Agents and Traces

Learn about Guardrails primitives to model agent behavior for guardrailing.

Invariant uses a simple yet powerful event-based trace model of agentic interactions, derived from the OpenAI chat data structure.

To use Guardrails and Explorer, your agentic interactions must be represented as a sequence of Event objects, as described below. If you are already using Gateway, all your LLM and MCP interactions will be automatically transformed into this format.

Execution Graph
User Message
(msg: Message)
msg.role == "user"
Assistant Message
(msg: Message)
msg.role == "assistant"
Tool Call
(call: ToolCall)
Tool Output
(output: ToolOutput)
JSON Trace{ "role": "user", "content": "Hello, how are you?" },
{ "role": "assistant", "content": "I'm doing well, thank you!", "tool_calls": [ { "id": "1", "type": "function", "function": { "name": "get_inbox", "arguments": {} } } ] },
{ "role": "tool", "tool_call_id": "1", "content": "1. Subject: Hello, From: Alice, Date: 2024-01-01, 2. Subject: Meeting, From: Bob, Date: 2024-01-02" }
The format of an agentic trace (hover over the nodes to see the relationships).

Agent Trace

An agent trace is a sequence of events generated by an agent during a multi-turn interaction or reasoning process. It consists of a sequence of Event objects, each being concretized as one of the classes defined below (Message, ToolCall, ToolOutput, etc.).

In a guardrailing rule, you can then use these types, to quantify and check your agentic traces for behaviors:

raise "Found pattern" if:
    (msg: Message) # <- checks every agent message (user, system, assistant)

    (call: ToolCall) # <- checks every tool call

    (output: ToolOutput) # <- checks every tool output

    # actual rule logic

The rule logic above will be applied to every Message, ToolCall, and ToolOutput object encountered during operation, enabling you to easily check your agents for bad behaviors.

Data Model

The underlying data model is defined as follows and derived from the OpenAI chat data structure.

Message

class Message(Event):
    role: str
    content: Optional[str] | list[Content]
    tool_calls: Optional[list[ToolCall]]

# base class for multi-modal content chunks
class Content:
    type: str

# text content
class TextContent(Content):
    type: str = "text"
    text: str

# image content
class ImageContent(Content):
    type: str = "image"
    image_url: str
role string

The role of the event, e.g., user, assistant, system, or something else.

content string | list[Content]

The content of the event, e.g., agent reasoning and intermediate results.

Content can be a string or a list of Content objects, i.e. text and image chunks.

tool_calls list[ToolCall]

A list of tool calls made by the agent as part of this message.

Examples

Simple message

{ "role": "user", "content": "Hello, how are you?" }

A message with a tool call

{ 
    "role": "assistant", 
    "content": "Checking your inbox...", 
    "tool_calls": [
        { 
            "id": "1", 
            "type": "function", 
            "function": { 
                "name": "get_inbox", 
                "arguments": {
                    "n": 10
                }
            }
        }
    ]
}

ToolCall

class ToolCall:
    id: str
    type: str
    function: Function

class Function:
    name: str
    arguments: dict
id string

A unique identifier for the tool call.

type string

The type of the tool call, e.g., function.

function Function

The function call made by the agent.

  • name string

    The name of the function called.

  • arguments dict

    The arguments passed to the function, encoded as a JSON dictionary.

Example

A tool call to get the latest 10 emails from the user's inbox.

{
    "id": "1",
    "type": "function",
    "function": {
        "name": "get_inbox",
        "arguments": {
            "n": 10
        }
    }
}

ToolOutput

A special event type for tool outputs, associated with a previous ToolCall.

class ToolOutput(Message):
    role: str
    content: str | list[Content]
    tool_call_id: Optional[str]
role string

The role of the event, e.g., tool.

content string

The content of the tool output, e.g., the result of a function call.

Content can be a string or a list of Content objects, i.e. text and image chunks (see Message for more details).

tool_call_id string

The identifier of a previous ToolCall that this output corresponds to.

Example

A tool output from the assistant to the tool.

{
    "role": "tool",
    "tool_call_id": "1",
    "content": "1. Subject: Hello, From: Alice, Date: 2024-01-01, 2. Subject: Meeting, From: Bob, Date: 2024-01-02"
}

Full Trace Example

The format suitable for Invariant is a list of Event objects. Here is an example of a trace with a user asking for their inbox, the assistant fetching the inbox, and the assistant listing the inbox contents.

[
    {
        "role": "user", 
        "content": "What's in my inbox?"
    }, 
    {
        "role": "assistant",
        "content": "Here are the latest emails.", 
        "tool_calls": [
            {
                "id": "1",
                "type": "function",
                "function": {
                    "name": "get_inbox",
                    "arguments": {}
                }
            }
        ]
    },
    {
        "role": "tool",
        "tool_call_id": "1",
        "content": "1. Subject: Hello, From: Alice, Date: 2024-01-0, 2. Subject: Meeting, From: Bob, Date: 2024-01-02"
    },
    {
        "role": "assistant",
        "content": "You have 2 new emails."
    }
]