Skip to main content

Pattern: Context Manager

The context manager pattern (with reflect.trace(...)) gives you full control over when the trace is submitted and lets you decide the review result after inspecting the agent’s output. It fits naturally into multi-step workflows where a decorator would be too rigid.
with reflect.trace(task)  →  ctx.augmented_task  →  agent runs tools  →  ctx.set_output  →  trace auto-submitted on exit
This example pairs Deep Agents with Exa for real-time web search and uses Reflect to build memory across research runs.

Prerequisites

export REFLECT_API_KEY=rf_live_...
export REFLECT_PROJECT_ID=your-project-id
export EXA_API_KEY=...
export OPENAI_API_KEY=sk-...      # or another provider key
Install dependencies:
pip install reflect-sdk deepagents exa-py
Optional env vars:
export REFLECT_API_URL=https://api.starlight-search.com  # defaults to localhost:8000
export DEEPAGENT_MODEL=openai:gpt-5.4-mini
export RESEARCH_QUERY="Latest breakthroughs in fusion energy"

Full example

deepagents_exa_quickstart.py
"""Deep Agents quickstart using Exa Search + Reflect memory loop.

Prerequisites:
- pip install deepagents exa-py
- Set EXA_API_KEY
- Set one model provider API key (for example OPENAI_API_KEY)
- Set REFLECT_PROJECT_ID and REFLECT_API_KEY

Optional env vars:
- REFLECT_API_URL (default: http://localhost:8000)
- DEEPAGENT_MODEL (default: openai:gpt-5.4-mini)
- RESEARCH_QUERY (default: What is the stock price of Apple and Nvidia?)
"""

from __future__ import annotations

import os

from deepagents import create_deep_agent
from exa_py import Exa
from reflect_sdk import ReflectClient
from reflect_sdk.converters import from_deepagents

BASE_URL = os.getenv("REFLECT_API_URL", "http://localhost:8000")
PROJECT_ID = os.getenv("REFLECT_PROJECT_ID") or "example"
REFLECT_API_KEY = os.getenv("REFLECT_API_KEY")
MODEL = os.getenv("DEEPAGENT_MODEL", "openai:gpt-5.4-mini")
TASK = os.getenv("RESEARCH_QUERY", "What is the stock price of Apple and Nvidia?")
MEMORY_LIMIT = 3
MEMORY_LAMBDA = 0.5
API_TIMEOUT = 180.0

research_instructions = """You are an expert researcher. Your job is to conduct thorough research and then write a polished report.

You have access to an internet search tool as your primary means of gathering information.

## `internet_search`

Use this to run an internet search for a given query. You can specify the max number of results to return and the topic.
Prefer high-quality primary sources and cite concrete facts from search results.
"""


def internet_search(query: str, max_results: int = 5):
    """Run an internet search using Exa."""
    exa = Exa(api_key=os.environ["EXA_API_KEY"])
    return exa.search(
        query,
        num_results=max_results,
        contents={"highlights": {"max_characters": 2000}},
    )


def main() -> None:
    if not os.getenv("EXA_API_KEY"):
        raise RuntimeError("Set EXA_API_KEY.")
    if not PROJECT_ID or not REFLECT_API_KEY:
        raise RuntimeError("Set REFLECT_PROJECT_ID and REFLECT_API_KEY.")

    reflect = ReflectClient(
        base_url=BASE_URL,
        api_key=REFLECT_API_KEY,
        project_id=PROJECT_ID,
        timeout=API_TIMEOUT,
    )

    with reflect.trace(TASK, limit=MEMORY_LIMIT, lambda_=MEMORY_LAMBDA) as ctx:
        agent = create_deep_agent(
            model=MODEL,
            tools=[internet_search],
            system_prompt=research_instructions,
        )
        result = agent.invoke({"messages": [{"role": "user", "content": ctx.augmented_task}]})
        print(result)
        trajectory = from_deepagents(result["messages"])
        ctx.set_output(
            trajectory=trajectory,
            model=MODEL,
            metadata={"source": "deepagents_exa_quickstart"},
        )


if __name__ == "__main__":
    main()

Run it

python deepagents_exa_quickstart.py
# or with a custom query:
RESEARCH_QUERY="Who founded Anthropic?" python deepagents_exa_quickstart.py

How it works

1

Open a trace context

reflect.trace(task) retrieves relevant memories and opens a trace that will be submitted when the with block exits.
with reflect.trace(TASK, limit=3, lambda_=0.5) as ctx:
    ...
# trace is submitted here, on __exit__
limit controls how many memories are retrieved. lambda_ balances semantic similarity vs. utility when ranking them (0 = pure similarity, 1 = pure utility).
2

Pass the augmented task to the agent

ctx.augmented_task is the original task with relevant memories from past runs prepended. Passing this to the agent means it can draw on what worked before.
result = agent.invoke({
    "messages": [{"role": "user", "content": ctx.augmented_task}]
})
3

Define a tool the agent can call

The agent can call internet_search to retrieve live data. Exa returns highlights from matching pages, which the agent cites in its report.
def internet_search(query: str, max_results: int = 5):
    exa = Exa(api_key=os.environ["EXA_API_KEY"])
    return exa.search(query, num_results=max_results,
                      contents={"highlights": {"max_characters": 2000}})
4

Convert messages and set output

from_deepagents maps the agent’s message list into Reflect’s trajectory format. Call ctx.set_output before the with block exits to attach the trajectory and metadata to the trace.
from reflect_sdk.converters import from_deepagents

trajectory = from_deepagents(result["messages"])
ctx.set_output(
    trajectory=trajectory,
    model=MODEL,
    metadata={"source": "deepagents_exa_quickstart"},
)

Adding a review

Pass result to ctx.set_output to close the learning loop at submission time:
ctx.set_output(
    trajectory=trajectory,
    model=MODEL,
    result="pass",          # or "fail"
    feedback_text="...",    # only needed on fail
)
Without result, the trace is stored with a pending review and can be reviewed later from the dashboard.

The lambda_ parameter

When retrieving memories, Reflect ranks candidates by a blended score:
score = (1 - lambda_) × similarity + lambda_ × q_value
  • lambda_ = 0 - pure semantic similarity (most relevant to this query)
  • lambda_ = 0.5 - balanced (default)
  • lambda_ = 1 - pure utility - memories from the most successful past runs)
As more traces are reviewed, utility scores improve and memory retrieval becomes increasingly useful.