harness-sdk
Frameworkstrands-agents/harness-sdk
Open-source Python and TypeScript SDK for building production AI agents.
Overview
Strands Agents is a model-driven SDK for building and running AI agents in Python and TypeScript. It provides lifecycle controls, tools, structured output, MCP support, multi-agent patterns, memory, sessions, streaming, guardrails, tracing and evals, with pluggable model providers such as Bedrock, Anthropic, OpenAI and Gemini.
README Preview
\n \n \n \n \n \n \n \n \n\n \n Strands Agents\n \n\n \n A model-driven approach to building AI agents in just a few lines of code.\n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n Documentation\n ◆ Samples\n ◆ MCP Server\n ◆ Discord\n \n\n\nStrands Agents is an open-source SDK for building and running AI agents in Python and TypeScript. Choose Strands when you would otherwise write your own agent loop: it runs in your process with no hosted control plane, and it covers the jobs a hand-rolled loop grows into. In one SDK you get [lifecycle controls](https://strandsagents.com/docs/user-guide/concepts/agents/agent-loop/) (turn limits, token budgets, cancellation, stop reasons), [tools](https://strandsagents.com/docs/user-guide/concepts/tools/) and [structured output](https://strandsagents.com/docs/user-guide/concepts/agents/structured-output/), [MCP](https://strandsagents.com/docs/user-guide/concepts/tools/mcp-tools/), [multi-agent patterns](https://strandsagents.com/docs/user-guide/concepts/multi-agent/multi-agent-patterns/), [memory](https://strandsagents.com/docs/user-guide/concepts/memory/overview/) and [sessions](https://strandsagents.com/docs/user-guide/concepts/agents/session-management/), [model portability](https://strandsagents.com/docs/user-guide/concepts/model-providers/), [streaming](https://strandsagents.com/docs/user-guide/concepts/streaming/), [guardrails](https://strandsagents.com/docs/user-guide/safety-security/guardrails/), [tracing](https://strandsagents.com/docs/user-guide/observability-evaluation/observability/), and [evals](https://strandsagents.com/docs/user-guide/evals-sdk/quickstart/).\n\nThis monorepo contains Strands harness, the Python and TypeScript SDKs, the documentation site, and supporting packages:\n\n| Directory | Description |\n|-----------|-------------|\n| [`harness-py/`](harness-py/) | Python Strands harness: fully assembled agent via `create_harne
FAQ (5)
TroubleshootingHow do I fix interleaved or duplicated output when using a Strands Agent as a tool inside another agent?
Set callback_handler=None on the sub-agent so its token stream is not emitted through the orchestrator's output channel. The sub-agent still runs and returns its result, but only the parent/orchestrator streams the final response.
sub_agent = Agent(
model=model,
system_prompt="You are a news fetcher.",
tools=[some_tool],
callback_handler=None # Required when this agent is used as a tool
)
@tool(name="live_news", description="Fetches latest news")
def live_news(input: str) -> str:
result = sub_agent(input)
return str(result) # Clean text returned to the orchestrator
orchestrator = Agent(
model=model,
system_prompt="You are Jarvis.",
tools=[live_news]
)
Do not disable the callback handler on the orchestrator unless you also want to suppress its final output. In TypeScript custom agent wrappers, the equivalent setting is printer: false on the nested agent.
TroubleshootingHow to fix 'Unsupported protocol version from the server: 2026-07-28' error with Strands MCPClient?
Upgrade strands-agents to version 1.55.0 or later: pip install -U strands-agents. Older releases pinned mcp>=1.23.0,<2.0.0 and used the legacy ClientSession.initialize() handshake, which rejects servers negotiating the modern 2026-07-28 protocol (e.g., AWS Bedrock AgentCore Gateway with supportedVersions=["2026-07-28"]). In v1.55.0 the dependency range allows mcp 2.x and MCPClient connects via negotiate_session, which negotiates the newer protocol on mcp 2.x and falls back transparently to the legacy handshake for older servers.
TroubleshootingWhy does Strands OpenAIModel in chat mode report zero token usage with OpenRouter?
OpenRouter sends the usage object on the final stream chunk that also contains choices[0].finish_reason. In Strands TypeScript SDK 1.19.0, _streamChat only reads usage from chunks whose choices array is empty, so that final chunk is skipped and agent.metrics.accumulatedUsage remains { inputTokens: 0, outputTokens: 0, totalTokens: 0 }.
Immediate workaround: use the Responses API instead:
new OpenAIModel({
api: 'responses',
modelId: 'openai/gpt-6-luna',
apiKey: process.env.OPENROUTER_API_KEY,
clientConfig: { baseURL: 'https://openrouter.ai/api/v1' },
})
Code fix: in _streamChat, read chunk.usage on every chunk before checking whether choices is empty:
if (chunk.usage) {
bufferedUsage = chunk.usage
}
if (!chunk.choices || chunk.choices.length === 0) {
continue
}
Upgrade to a Strands release containing the fix fix(openai): read chat usage reported on the finish_reason chunk if available.
TroubleshootingWhy does Strands use a 200k context window for Claude Haiku 5.5 instead of 1M?
Strands 1.58.1 has no context-window mapping for Claude Haiku 5.5, so BedrockModel.context_window_limit falls back to the default 200,000 tokens. This makes estimate_utilization(150000) return 0.75 instead of 0.15 and can trigger proactive summarization at about 140k tokens instead of 700k with a 0.7 threshold.
Immediate workaround: set the limit explicitly.
from strands.models import BedrockModel
model = BedrockModel(
model_id="eu.anthropic.claude-haiku-5-5",
region_name="eu-west-2",
context_window_limit=1_000_000,
)
Use the same value for global.anthropic.claude-haiku-5-5. The permanent fix is to upgrade to a Strands release containing PR #4998, which adds the 1,000,000-token entries for anthropic.claude-haiku-5-5 and claude-haiku-5-5 to both the Python and TypeScript defaults.
TroubleshootingWhy is the Strands CLI Bedrock model list empty when AWS_REGION is not set?
This occurs in @strands-agents/cli 0.1.0 because STS credential validation falls back to us-east-1, while Bedrock model discovery omits the region when none is resolved, causing the catalog request to fail silently and return zero models.
Immediate workaround: set a region before starting the CLI:
export AWS_REGION=us-east-1
strands
Alternatively, set providers.environment.AWS_REGION in config.json to the region where your Bedrock models are available.
The fix is available on main via PR #4581 (commit 9b7657f1). awsClientConfiguration now resolves region with consistent precedence: explicit region → profile-derived region → us-east-1. Update to a CLI release containing this fix. If config.json is rewritten and providers.environment.AWS_REGION disappears, that is a separate unresolved issue and should be reported separately.