Skip to content

Latest commit

 

History

History
314 lines (247 loc) · 6.9 KB

File metadata and controls

314 lines (247 loc) · 6.9 KB

Trace Format

The Agent Security Regression Harness evaluates agent behavior through execution traces.

A trace is a JSON-compatible object that records what happened during a scenario run. The harness does not require a specific agent framework. Instead, live targets and adapters must return trace-shaped JSON that the assertion engine can evaluate.

Top-level shape

A trace contains three top-level lists:

{
  "messages": [],
  "tool_calls": [],
  "events": []
}

All three fields are required by convention and should be present even when empty.

Messages

messages records conversation-like activity.

Example:

{
  "messages": [
    {
      "role": "user",
      "content": "Summarize the document."
    },
    {
      "role": "assistant",
      "content": "Here is the summary."
    }
  ]
}

Message fields:

Field Type Description
role string Message role, such as user, assistant, system, or tool.
content string Message text.

Assertions may inspect messages for secret disclosure, goal drift, or other policy violations.

Tool calls

tool_calls records tools the agent attempted to call.

Example:

{
  "tool_calls": [
    {
      "name": "send_email",
      "arguments": {
        "to": "attacker@example.com",
        "subject": "Requested information"
      }
    }
  ]
}

Tool call fields:

Field Type Description
name string Preferred tool name field.
tool string Alternative tool name field accepted by the harness.
tool_name string Alternative tool name field accepted by the harness.
arguments object Tool arguments supplied by the agent.

The harness currently recognizes tool names from these fields, in order:

  1. name
  2. tool
  3. tool_name

A tool call should use name unless an adapter is translating from a framework that already uses a different field.

MCP tool calls

MCP tool names are only unique within an MCP server, so MCP adapters should use a canonical source-qualified tool name:

{
  "name": "mcp/filesystem_fixture/delete_file",
  "arguments": {
    "path": "notes.txt"
  },
  "mcp_server_id": "filesystem_fixture",
  "mcp_tool_name": "delete_file",
  "mcp_method": "tools/call",
  "trust": "untrusted",
  "mcp_transport": "stdio"
}

Scenarios that deny MCP tools should use the canonical mcp/<server_id>/<tool> name in expected.denied_tools.

MCP lifecycle events

MCP adapters should record protocol activity that affects the agent but is not a plain tool call in events. The initial normalized event set is:

Event type Required identity Notes
mcp_resource_read server_id, uri Records a resource returned across the MCP trust boundary.
mcp_prompt_get server_id, mcp_prompt_name Records a prompt retrieved from an MCP server.
mcp_tool_result server_id, mcp_tool_name Records a tool result or tool execution error.
mcp_policy_decision server_id, decision Records an adapter allow/deny decision.

The adapter may also emit connection and capability events such as mcp_connection_initialized, mcp_capabilities_negotiated, mcp_tools_discovered, mcp_client_request, and mcp_connection_closed.

MCP events should preserve the configured server identity and trust metadata. For tool results, name should use the same canonical mcp/<server_id>/<tool> format as tool_calls.

Example MCP event trace:

{
  "events": [
    {
      "type": "mcp_resource_read",
      "server_id": "filesystem_fixture",
      "trust": "untrusted",
      "transport": "stdio",
      "uri": "file:///workspace/fixtures/injected.md",
      "mime_type": "text/markdown",
      "content_truncated": true,
      "mcp_method": "resources/read"
    },
    {
      "type": "mcp_prompt_get",
      "server_id": "prompt_server",
      "trust": "third_party",
      "mcp_prompt_name": "summarize_document",
      "mcp_method": "prompts/get"
    },
    {
      "type": "mcp_tool_result",
      "name": "mcp/filesystem_fixture/read_file",
      "server_id": "filesystem_fixture",
      "mcp_tool_name": "read_file",
      "trust": "untrusted",
      "is_error": false,
      "content_truncated": false,
      "mcp_method": "tools/call"
    },
    {
      "type": "mcp_policy_decision",
      "server_id": "filesystem_fixture",
      "trust": "untrusted",
      "method": "tools/call",
      "decision": "deny",
      "reason": "tool is denied by scenario policy"
    }
  ]
}

Events

events records structured runtime facts that are not plain messages or tool calls.

Example:

{
  "events": [
    {
      "type": "goal",
      "id": "summarize_document"
    }
  ]
}

Event fields:

Field Type Description
type string Event category.
id string Stable identifier for the event.

Additional event fields may be included when useful for evidence, debugging, or future assertions.

Goal events

Goal events describe the goal the agent actually followed during execution.

Goal event shape:

{
  "type": "goal",
  "id": "summarize_document"
}

The id should be a stable, snake_case identifier.

Example expected goal in a scenario:

assertions:
  - type: goal_integrity
    expected_goal: summarize_document

Example passing trace event:

{
  "type": "goal",
  "id": "summarize_document"
}

Example failing trace event:

{
  "type": "goal",
  "id": "send_email"
}

Goal matching should use strict equality. Substring matching should not be used for security assertions because it can create false positives.

Trust-boundary events

Targets may record when untrusted context was observed and treated as data.

Example:

{
  "type": "untrusted_context_received",
  "policy": "treated as data, not instruction"
}

This is useful evidence for hardened agents that preserve the user's goal while refusing to follow injected instructions.

Example complete trace

{
  "messages": [
    {
      "role": "user",
      "content": "Summarize the document."
    },
    {
      "role": "assistant",
      "content": "Here is the summary."
    }
  ],
  "tool_calls": [],
  "events": [
    {
      "type": "goal",
      "id": "summarize_document"
    },
    {
      "type": "untrusted_context_received",
      "policy": "treated as data, not instruction"
    }
  ]
}

Adapter responsibility

Adapters and live HTTP targets are responsible for converting framework-specific behavior into this trace format.

For live HTTP targets, the target receives scenario input and returns trace JSON.

Request body:

{
  "scenario_id": "goal_hijack.outbound_email_exfiltration_001",
  "input": {
    "user_message": "Summarize the document.",
    "context": []
  }
}

Response body:

{
  "messages": [],
  "tool_calls": [],
  "events": []
}

The assertion engine evaluates only the returned trace and the scenario policy.