Skip to main content
The Trajectory extension allows you to visualize the step-by-step reasoning process of your agent as it runs. Trajectory steps appear as expandable sections in the UI, helping users understand your agent’s thought process, making the interaction more transparent and trustworthy.

Example: Basic Usage

# Copyright 2025 © BeeAI a Series of LF Projects, LLC
# SPDX-License-Identifier: Apache-2.0

import os
from time import sleep
from typing import Annotated

from a2a.types import Message
from agentstack_sdk.a2a.extensions import TrajectoryExtensionServer, TrajectoryExtensionSpec
from agentstack_sdk.server import Server
from agentstack_sdk.server.context import RunContext

server = Server()


@server.agent(
    name="Docs Trajectory Agent",
)
async def trajectory_basic_usage_example(
    input: Message, context: RunContext, trajectory: Annotated[TrajectoryExtensionServer, TrajectoryExtensionSpec()]
):
    yield trajectory.trajectory_metadata(
        title="Planning", content="Analyzing the user request to determine the best approach..."
    )
    sleep(3)  # Sleep so that you can watch the trajectory steps unfold

    yield trajectory.trajectory_metadata(title="Execution", content="Processing data with temperature=0.7...")
    sleep(3)

    yield "Final result goes here"


def run():
    server.run(host=os.getenv("HOST", "127.0.0.1"), port=int(os.getenv("PORT", 8000)))


if __name__ == "__main__":
    run()

1

Import the trajectory extension

Import TrajectoryExtensionServer and TrajectoryExtensionSpec from agentstack_sdk.a2a.extensions.
2

Inject the extension

Add a trajectory parameter to your agent function using the Annotated type hint with TrajectoryExtensionSpec().
3

Yield trajectory metadata

Call yield trajectory.trajectory_metadata() with a title and content to add a step to the trajectory.

Markdown Support

The content field of trajectory_metadata supports Markdown, which is rendered directly in the UI. Supported elements include:
  • Headers
  • Bold and italic text
  • Ordered and unordered lists
  • Tables
  • Code blocks
  • Links
  • Checklists
yield trajectory.trajectory_metadata(
    title="Checklist",
    content="""
- [x] Load data
- [x] Validate schema
- [ ] Run inference
- [ ] Generate report
"""
)

Grouping Trajectories

Use the group_id parameter to update trajectory content in the UI. Each update replaces the previous content (and title, if defined) for the same group_id:
# Initial search status
yield trajectory.trajectory_metadata(
    title="Web search",
    content="Querying search engines...",
    group_id="websearch"
)

# Update with results
sleep(3)
yield trajectory.trajectory_metadata(
    content="Found 8 results",
    group_id="websearch"
)
sleep(3)
yield trajectory.trajectory_metadata(
    content="Found 8 results\nAnalyzed 3/8 results",
    group_id="websearch"
)
sleep(3)
yield trajectory.trajectory_metadata(
    content="Found 8 results\nAnalyzed 8/8 results",
    group_id="websearch"
)
sleep(3)

# Final update
yield trajectory.trajectory_metadata(
    title="Web search finished",
    content="Found 8 results\nAnalyzed 3/8 results\nExtracted key information",
    group_id="websearch"
)

Common Patterns

Progress Steps:
yield trajectory.trajectory_metadata(title="Step 1", content="Loading data...")
yield trajectory.trajectory_metadata(title="Step 2", content="Processing...")
yield trajectory.trajectory_metadata(title="Step 3", content="Generating output...")
Decision Points:
yield trajectory.trajectory_metadata(
    title="Tool Selection",
    content="Choosing search tool based on query type: factual"
)
Error Handling:
yield trajectory.trajectory_metadata(
    title="Retry Attempt",
    content="First attempt failed, trying alternative approach..."
)
Multi-step Process with Live Updates:
# Use group_id to show progress updates in a single section
yield trajectory.trajectory_metadata(
    title="Data Processing",
    content="Starting...",
    group_id="processing"
)
yield trajectory.trajectory_metadata(
    content="Processing batch 1/10...",
    group_id="processing"
)
yield trajectory.trajectory_metadata(
    content="Processing batch 10/10...",
    group_id="processing"
)
yield trajectory.trajectory_metadata(
    content="Processing complete! Processed 10 items",
    group_id="processing"
)

Example: Advanced Usage

For a more advanced example, see trajectory_agent.py.