Skip to main content
The Strands Agents integration instruments the Strands Agent SDK via its hook system to capture agent invocations, model calls, tool usage, and token metrics. Features:
  • No OpenTelemetry setup required
  • Automatic input/output capture from agent invocations
  • Model call tracking with token usage
  • Tool call span tracking
  • Works with both TypeScript and Python SDKs

Installation

Quick Start


What Gets Traced

The Strands integration automatically captures:
  • Agent invocations — input prompt (last user message), output text, model name
  • Token usage — prompt_tokens, completion_tokens, and cached_tokens (from Bedrock/Anthropic cacheReadInputTokens / cacheCreationInputTokens)
  • Model calls — output and usage extracted from each model call within an invocation
  • Tool call spans — individual tool spans tracked via interaction.track_tool() with name, input, output, duration (ms), and error
  • Finish reason — stop_reason or finish_reason from model responses (e.g., end_turn, tool_use), included in properties as strands.finish_reason
  • Errors — captured and re-raised; telemetry failures never crash your pipeline

Configuration


Projects

Route events to a specific project by passing its slug as projectId (project_id in Python):
This sets the X-Raindrop-Project-Id header on every event. Omit it (or pass "default") to use your org’s default Production project, which is the existing behavior. Single-project orgs need nothing new.

Multiple projects in one process

Available in raindrop-ai>=0.0.56. When one service runs several Strands agents that should report to different projects, create one RaindropStrands wrapper per project. Each wrapper owns its own raindrop.Raindrop client, so the two route independently — there is no shared module-level state:
Each wrapper owns its configuration and delivery pipeline, so agents handled by different wrappers route independently. To share a single client across wrappers (or with the module-level API), construct a raindrop.Raindrop yourself and pass it via client=:

Identifying Users


Signals (Feedback)

Track user feedback on AI responses:

Tool catalog capture (ai.prompt.tools)

TypeScript. Every strands.model.call span records the agent’s registered tool specs (agent.toolRegistry, the same list the SDK hands the model on each call) as ai.prompt.tools. Pass tools on createRaindropStrands(...) to record a different list instead (it replaces the inferred one; tools: [] records an empty catalog). Python. raindrop-strands ≥ 0.0.13 binds the agent’s registered tool specs (agent.tool_registry.get_all_tool_specs(), the list Strands passes to Model.stream(tool_specs=...) right after the before-model hooks) in on_before_model_call and releases them in on_after_model_call, so the model span opened in between carries ai.prompt.tools with the JSON Schema from inputSchema.json intact. Capture is exact. Pass tools= on RaindropStrands(...) / create_raindrop_strands(...) to record a different list for every model call of every agent registered with that handler (it replaces the registry list; tools=[] records an empty catalog; no per-call override). Follows TRACELOOP_TRACE_CONTENT; needs raindrop-ai ≥ 0.0.70. See Tool catalog capture for the attribute format, the absent / [] semantics and the override shapes accepted.

Flush & Shutdown

Always flush before your process exits to ensure all data is sent:

Captured Properties

The following properties are automatically included in tracked events:

Token Tracking

The integration automatically captures token usage from model responses: Tokens are extracted from both individual model call responses (stop_response.usage) and accumulated metrics (result.metrics.accumulated_usage).

Finish Reason

The model’s stop reason is captured automatically and included in event properties as strands.finish_reason. The integration checks stop_reason first (Bedrock convention), then falls back to finish_reason.

Factory Function

A create_raindrop_strands() factory is available for convenience:

Application Git metadata (Python)

RaindropStrands(...) and create_raindrop_strands(...) accept the keyword-only app_git option. It defaults to True: explicit Raindrop Git environment or deployment context is applied immediately, and the base SDK may perform one bounded background local-Git lookup from the process working directory. Event capture, flush, and shutdown never wait for that lookup. Pass False to disable enrichment, or pass an AppGitOptions mapping with commit_sha, commit_dirty, branch, source_directory, detect_branch, and/or auto_detect. Automatic branch discovery remains opt-in through detect_branch=True (or RAINDROP_GIT_DETECT_BRANCH=true). For an ordinary in-process application, the process working directory is treated as the application-under-test checkout. A remote, coding, workflow, or observer process must not rely on its own checkout: pass app_git=False, provide explicit revision values, or set source_directory to the actual application checkout. Canonical per-operation properties remain authoritative. When supplying client=, configure app_git while constructing that Raindrop client; the supplied client is authoritative and the wrapper’s app_git argument does not reconfigure it. Release order is deliberate: first publish the base SDK feature, then publish the wrapper feature release with its minimum dependency coordinated to that base release. The existing raindrop-ai lower bound remains compatible, but application Git metadata is unavailable on an older core and must not be claimed complete until the base is upgraded. Until coordination assigns a released version, the wrapper checks for an explicit base app_git parameter and omits the option when unsupported. Explicit non-default configuration is debug-logged and omitted. Unsupported app_git is determined by signature inspection before construction, not by retrying initialization after a TypeError; Git configuration adds no initialization attempts and does not change any existing framework-specific initialization fallback.

Known Limitations

  • Streaming: The integration captures the final result of each model call. Streaming token-by-token output is not individually traced.
  • Multi-agent: Each agent needs its own registerHooks() / register_hooks() call. Nested agent hierarchies are not automatically linked.
  • Python WeakRef: The Python handler uses id(agent) for internal tracking since some agent-like objects don’t support weak references. Context is cleaned up explicitly after each invocation.

That’s it! You’re ready to explore your Strands agent events in the Raindrop dashboard. Ping us on Slack or email us if you get stuck!