Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 28 additions & 28 deletions python/tracing/strands-agents/01_basic_agent.py
Original file line number Diff line number Diff line change
@@ -1,42 +1,42 @@
"""Run one Strands agent call with Respan tracing."""

from _shared import create_gateway_model, create_respan, finish_respan, new_run_id
from respan import propagate_attributes, workflow
from strands import Agent

from _shared import create_gateway_model, create_respan, new_run_id

WORKFLOW_NAME = "Strands Basic Example"


def run_basic_agent() -> None:
run_id = new_run_id("basic")
respan = create_respan(example_name="basic", run_id=run_id)

agent = Agent(
name=WORKFLOW_NAME,
model=create_gateway_model(),
system_prompt="Answer in one short sentence.",
)

@workflow(name=WORKFLOW_NAME)
def run_workflow():
return agent("What is one practical use for distributed tracing?")

with propagate_attributes(
trace_group_identifier=WORKFLOW_NAME,
custom_identifier=run_id,
customer_identifier="strands-example-user",
thread_identifier=f"{run_id}-thread",
metadata={
"script": "01_basic_agent.py",
"run_id": run_id,
"workflow_name": WORKFLOW_NAME,
},
):
result = run_workflow()

print(f"RESPAN_EXAMPLE_RUN_ID={run_id}")
print(result)
try:
agent = Agent(
name=WORKFLOW_NAME,
model=create_gateway_model(),
system_prompt="Answer in one short sentence.",
)

@workflow(name=WORKFLOW_NAME)
def run_workflow(prompt: str) -> dict[str, str]:
return {"answer": str(agent(prompt))}

with propagate_attributes(
trace_group_identifier=WORKFLOW_NAME,
custom_identifier=run_id,
customer_identifier="strands-example-user",
thread_identifier=f"{run_id}-thread",
metadata={
"script": "01_basic_agent.py",
"run_id": run_id,
"example_run_id": run_id,
},
):
result = run_workflow("What is one practical use for distributed tracing?")
print(f"RESPAN_EXAMPLE_RUN_ID={run_id}")
print(result)
finally:
finish_respan(respan)


if __name__ == "__main__":
Expand Down
60 changes: 31 additions & 29 deletions python/tracing/strands-agents/02_tool_use.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
"""Run a Strands agent tool call with Respan tracing."""

from _shared import create_gateway_model, create_respan, finish_respan, new_run_id
from respan import propagate_attributes, workflow
from strands import Agent, tool

from _shared import create_gateway_model, create_respan, new_run_id

WORKFLOW_NAME = "Strands Tool Use Example"


Expand All @@ -17,33 +16,36 @@ def get_weather(city: str) -> str:
def run_tool_use() -> None:
run_id = new_run_id("tool")
respan = create_respan(example_name="tool_use", run_id=run_id)

agent = Agent(
name=WORKFLOW_NAME,
model=create_gateway_model(),
tools=[get_weather],
system_prompt="Use available tools when weather data is requested.",
)

@workflow(name=WORKFLOW_NAME)
def run_workflow():
return agent("Use the get_weather tool to answer: weather in Seattle?")

with propagate_attributes(
trace_group_identifier=WORKFLOW_NAME,
custom_identifier=run_id,
customer_identifier="strands-example-user",
thread_identifier=f"{run_id}-thread",
metadata={
"script": "02_tool_use.py",
"run_id": run_id,
"workflow_name": WORKFLOW_NAME,
},
):
result = run_workflow()

print(f"RESPAN_EXAMPLE_RUN_ID={run_id}")
print(result)
try:
agent = Agent(
name=WORKFLOW_NAME,
model=create_gateway_model(),
tools=[get_weather],
system_prompt="Use available tools when weather data is requested.",
)

@workflow(name=WORKFLOW_NAME)
def run_workflow(prompt: str) -> dict[str, str]:
return {"answer": str(agent(prompt))}

with propagate_attributes(
trace_group_identifier=WORKFLOW_NAME,
custom_identifier=run_id,
customer_identifier="strands-example-user",
thread_identifier=f"{run_id}-thread",
metadata={
"script": "02_tool_use.py",
"run_id": run_id,
"example_run_id": run_id,
},
):
result = run_workflow(
"Use the get_weather tool to answer: weather in Seattle?"
)
print(f"RESPAN_EXAMPLE_RUN_ID={run_id}")
print(result)
finally:
finish_respan(respan)


if __name__ == "__main__":
Expand Down
60 changes: 31 additions & 29 deletions python/tracing/strands-agents/03_propagated_attributes.py
Original file line number Diff line number Diff line change
@@ -1,43 +1,45 @@
"""Run Strands with per-request Respan attributes."""

from _shared import create_gateway_model, create_respan, finish_respan, new_run_id
from respan import propagate_attributes, workflow
from strands import Agent

from _shared import create_gateway_model, create_respan, new_run_id

WORKFLOW_NAME = "Strands Attribute Propagation Example"


def run_propagated_attributes() -> None:
run_id = new_run_id("attrs")
respan = create_respan(example_name="propagated_attributes", run_id=run_id)

agent = Agent(
name=WORKFLOW_NAME,
model=create_gateway_model(),
system_prompt="You help support teams triage observability questions.",
)

@workflow(name=WORKFLOW_NAME)
def run_workflow():
return agent("Give one trace-debugging tip for a failing tool call.")

with propagate_attributes(
trace_group_identifier=WORKFLOW_NAME,
custom_identifier=run_id,
customer_identifier="customer_123",
thread_identifier=f"{run_id}-support-thread",
metadata={
"script": "03_propagated_attributes.py",
"run_id": run_id,
"workflow_name": WORKFLOW_NAME,
"plan": "pro",
},
):
result = run_workflow()

print(f"RESPAN_EXAMPLE_RUN_ID={run_id}")
print(result)
try:
agent = Agent(
name=WORKFLOW_NAME,
model=create_gateway_model(),
system_prompt="You help support teams triage observability questions.",
)

@workflow(name=WORKFLOW_NAME)
def run_workflow(prompt: str) -> dict[str, str]:
return {"answer": str(agent(prompt))}

with propagate_attributes(
trace_group_identifier=WORKFLOW_NAME,
custom_identifier=run_id,
customer_identifier="customer_123",
thread_identifier=f"{run_id}-support-thread",
metadata={
"script": "03_propagated_attributes.py",
"run_id": run_id,
"example_run_id": run_id,
"plan": "pro",
},
):
result = run_workflow(
"Give one trace-debugging tip for a failing tool call."
)
print(f"RESPAN_EXAMPLE_RUN_ID={run_id}")
print(result)
finally:
finish_respan(respan)


if __name__ == "__main__":
Expand Down
48 changes: 48 additions & 0 deletions python/tracing/strands-agents/04_structured_output.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
"""Trace a real Strands structured-output invocation."""

from _shared import create_gateway_model, create_respan, finish_respan, new_run_id
from pydantic import BaseModel
from respan import propagate_attributes, workflow
from strands import Agent

WORKFLOW_NAME = "Strands Structured Output Example"


class TraceTip(BaseModel):
title: str
action: str


def main() -> None:
run_id = new_run_id("structured")
respan = create_respan("structured_output", run_id)
try:
agent = Agent(name=WORKFLOW_NAME, model=create_gateway_model())

@workflow(name=WORKFLOW_NAME)
def run_workflow(prompt: str) -> dict[str, str]:
result = agent(prompt, structured_output_model=TraceTip)
parsed = result.structured_output
return (
parsed.model_dump()
if parsed
else {"error": "missing structured output"}
)

with propagate_attributes(
trace_group_identifier=WORKFLOW_NAME,
custom_identifier=run_id,
metadata={
"run_id": run_id,
"example_run_id": run_id,
"script": "04_structured_output.py",
},
):
result = run_workflow("Return one short distributed tracing debugging tip.")
print(result)
finally:
finish_respan(respan)


if __name__ == "__main__":
main()
43 changes: 43 additions & 0 deletions python/tracing/strands-agents/05_expected_provider_error.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
"""Trace a bounded expected Strands provider connection failure."""

from _shared import create_gateway_model, create_respan, finish_respan, new_run_id
from respan import propagate_attributes, workflow
from strands import Agent

WORKFLOW_NAME = "Strands Expected Provider Error"


def main() -> None:
run_id = new_run_id("provider-error")
respan = create_respan("expected_provider_error", run_id)
try:
agent = Agent(
name=WORKFLOW_NAME,
model=create_gateway_model(base_url="http://127.0.0.1:1/v1"),
)

@workflow(name=WORKFLOW_NAME)
def run_workflow(prompt: str) -> dict[str, str]:
return {"answer": str(agent(prompt))}

try:
with propagate_attributes(
trace_group_identifier=WORKFLOW_NAME,
custom_identifier=run_id,
metadata={
"run_id": run_id,
"example_run_id": run_id,
"script": "05_expected_provider_error.py",
},
):
run_workflow("This request is expected to fail before generation.")
except Exception as exc: # noqa: BLE001 - provider SDK exception surface varies
print({"expected_error": type(exc).__name__})
else:
raise AssertionError("expected provider failure did not occur")
finally:
finish_respan(respan)


if __name__ == "__main__":
main()
19 changes: 13 additions & 6 deletions python/tracing/strands-agents/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,22 @@ Optional variables:
python -m venv .venv
. .venv/bin/activate
pip install -r requirements.txt
python 01_basic_agent.py
python 02_tool_use.py
python 03_propagated_attributes.py
RESPAN_EXAMPLE_RUN_ID=strands-check python run_all.py
```

Each script prints a `RESPAN_EXAMPLE_RUN_ID` value. Use that value to find the
exact trace in Respan metadata or custom identifier filters. The trace workflow
name and trace group identify the example:
For local package development, link the instrumentation after installing the
portable registry requirements:

```bash
pip install -e ../../../../respan/python-sdks/instrumentations/respan-instrumentation-strands-agents
```

`run_all.py` runs every script with one exact marker, continues after a failed
or timed-out child, and exits nonzero after reporting the aggregate failures.
Every script flushes and shuts down Respan in `finally`. The suite covers:

- `Strands Basic Example`
- `Strands Tool Use Example`
- `Strands Attribute Propagation Example`
- `Strands Structured Output Example`
- `Strands Expected Provider Error`
Loading