Doramagic Project Pack · Human Manual
harness-sdk
A model-driven approach to building AI agents in just a few lines of code.
Monorepo Architecture & SDKs Overview
Related topics: Agent Loop, Tools & Hooks, Plugins, Bidirectional Streaming & WASM Interop
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Agent Loop, Tools & Hooks, Plugins, Bidirectional Streaming & WASM Interop
Monorepo Architecture & SDKs Overview
Purpose and Scope
The Strands Agents harness-sdk repository is a multi-package monorepo that hosts the Strands agent framework across several language targets, build systems, and supporting tooling. Its primary purpose is to provide a single source of truth from which Python-native, TypeScript-native, and WebAssembly-bridged SDKs are derived, along with the documentation, design proposals, and team policies that govern them.
The repository coordinates three first-class surfaces:
- A pure Python SDK (
strands-py) — the original Strands implementation and the canonical reference for the agent loop, model providers, and tool ecosystem. - A TypeScript SDK (
strands-ts) — written in TypeScript and published to the npm ecosystem. - A WASM-bridged package (
strands-py-wasm+strands-wasm) — a WebAssembly component built from the TypeScript SDK that is loaded and driven by Python throughwasmtime-py, enabling Python users to consume the TypeScript agent implementation.
Around these core SDKs, the monorepo also houses the documentation site (site/), the design-proposal process (designs/), the team's internal doctrine (team/), and developer tooling such as the strandly toolchain. Source: README.md.
Community alignment. Multiple open feature requests target the breadth of language targets and interop surface: a TypeScript/Node SDK (#156), a Go SDK (#616), a Java SDK (#240), and AG-UI protocol support (#140). The monorepo structure already accommodates the TS direction; Go and Java remain future work.
High-Level Repository Layout
The repository is organized into discrete top-level packages, each with a focused responsibility. The table below summarizes the layout that can be derived from the README and package contents.
| Path | Role | Notes |
|---|---|---|
strands-py/ | Pure Python SDK | The original, canonical Strands implementation; pip install strands-agents. |
strands-ts/ | TypeScript SDK | Published to npm; defines streaming, models, and tools. |
strands-wasm/ | WASM build tooling | Monorepo developer guide; describes WIT contracts and the build pipeline. |
strands-py-wasm/ | Python wrapper around the WASM component | Installed as strands-py-wasm; exposes generated Python bindings. |
strandly/ | Toolchain CLI | Linked to PATH by the bootstrap script. |
site/ | Documentation site (Astro + Starlight) | Builds API references for both Python and TypeScript SDKs. |
designs/ | RFC-style design proposals | Captures context, decision, and consequences for large features. |
team/ | Internal team doctrine | Tenets, decisions, API bar, agent guidelines. |
Source: README.md, strands-wasm/README.md, team/README.md.
Architecture Overview
The monorepo is intentionally layered. The diagram below illustrates the relationship between language targets, the WASM bridge, the documentation site, and the governance process.
graph TD
Repo[harness-sdk Monorepo]
Py[strands-py: Python SDK]
TS[strands-ts: TypeScript SDK]
WASMTool[strands-wasm: Build Tooling]
WASMPy[strands-py-wasm: Python + WASM]
Site[site: Astro/Starlight Docs]
Designs[designs: RFCs]
Team[team: Tenets & Decisions]
Strandly[strandly: CLI Toolchain]
Repo --> Py
Repo --> TS
Repo --> WASMTool
Repo --> WASMPy
Repo --> Site
Repo --> Designs
Repo --> Team
Repo --> Strandly
TS -->|compiled to| WASMTool
WASMTool -->|produces .wasm| WASMPy
WASMPy -->|loaded by| Py
Site -->|clones & generates| Py
Site -->|clones & generates| TS
Designs -->|feeds| Repo
Team -->|guides| Repo
Strandly -->|builds & links| WASMToolSource: strands-wasm/README.md, site/package.json.
Component Responsibilities
strands-pyis the public Python package. It exposes theAgentclass, tool decorators, and a large family of model providers. The README's "Quick Start" example usesfrom strands import Agentandpip install strands-agents strands-agents-tools. Source: README.md.strands-tsis the TypeScript counterpart. It defines streaming event types (e.g.ToolUseInputDelta,ReasoningContentDelta,CitationsDelta,Usage) and base model configuration (BaseModelConfig,StreamOptions). Source: strands-ts/src/models/streaming.ts, strands-ts/src/models/model.ts.strands-wasmis the build-time tooling and developer guide that explains how the TS SDK is compiled into a WebAssembly component (strands-agent.wasm) and how Python loads it viawasmtime-py. Source: strands-wasm/README.md.strands-py-wasmis the Python distribution that re-exports a generated_generatedmodule and a curatedtypessurface, allowing Python code to call into the WASM guest. Source: strands-py-wasm/src/strands/_generated/__init__.py, strands-py-wasm/src/strands/types.py.site/is the documentation site built with Astro and Starlight. Itspackage.jsondefines scripts to clone both SDKs and regenerate API references for each. Source: site/package.json.designs/formalizes the design-proposal process. It documents the template, lifecycle, and "no designs have been accepted yet" current state. Source: designs/README.md.team/contains the project's doctrine:TENETS.md,DECISIONS.md,API_BAR_RAISING.md, andAGENT_GUIDELINES.md. Source: team/README.md.strandly/provides the CLI toolchain that the bootstrap workflow links intoPATH. Source: strands-wasm/README.md.
The WASM Bridge
The most architecturally distinctive piece of the monorepo is the bridge that lets Python host a TypeScript agent. The TS SDK is compiled to a WebAssembly component; Python loads this component via wasmtime-py and drives it. Source: strands-wasm/README.md.
WIT Contract
The contract between the WASM "guest" (TypeScript) and the Python "host" is defined in a single WIT file. It separates responsibilities cleanly:
- Exports (TS implements, Python calls): The
apiinterface — agent construction, streaming, conversation management. All model provider HTTP calls (Bedrock, Anthropic, OpenAI, Gemini) happen inside the WASM guest. - Imports (Python implements, TS calls back into):
tool-providerfor executing Python-defined tools, andhost-logfor routing log entries to Python's logging framework.
When the TS agent loop decides a tool needs to run, it calls the tool-provider import which crosses the WASM boundary back to Python where the actual tool function lives. Source: strands-wasm/README.md.
graph LR
PyAgent[Python host: Agent loop & tools]
WIT[wit/agent.wit contract]
TSAgent[TypeScript guest: agent loop]
Models[Model providers in WASM]
Tools[Python-defined tools]
Logs[Python logging]
PyAgent -->|drives| TSAgent
WIT --> PyAgent
WIT --> TSAgent
TSAgent --> Models
TSAgent -->|tool-provider import| Tools
PyAgent -->|exports api| WIT
TSAgent -->|host-log import| LogsSource: strands-wasm/README.md.
Bootstrap and Build
The first-time setup is a single command. From the repository root:
git clone https://github.com/strands-agents/sdk-python.git
cd sdk-python
npm install
npm run dev -- bootstrap
bootstrap installs toolchains, links strandly to PATH, generates type bindings, builds all layers, installs strands-py-wasm, and runs all tests. Source: strands-wasm/README.md.
Generated Python Bindings
strands-py-wasm exposes a large generated surface from _generated/. The list of re-exported names includes content block types (TextBlock, ImageBlock, VideoBlock, DocumentBlock, CitationsBlock), tool types (ToolUseBlock, ToolResultBlock, ToolSpec), model types (BedrockModel, AnthropicModel, OpenaiModel, GoogleModel, CustomModel), multi-agent types (SwarmConfig, GraphConfig, HandoffEvent), retry types (ExponentialBackoff, ConstantBackoff), session types (SessionManager, SlidingWindowConversationManager, SummarizingConversationManager), and many more. Source: strands-py-wasm/src/strands/_generated/__init__.py.
The curated public surface is narrowed in types.py. Some stream-oriented types are intentionally dropped from the public re-export because they are not part of the host API:
| Dropped symbol | Reason / category |
|---|---|
Datetime, Duration, Instant | Time primitives not surfaced at the boundary. |
Error | Underlying error primitive; users import the typed exceptions instead. |
InputStream, OutputStream, Pollable | Async I/O primitives used internally by the WASM layer. |
The curated surface then re-exports the remaining symbols and adds convenience union types such as ModelInput, ConversationManagerInput, VendedToolInput, and VendedPluginInput. Source: strands-py-wasm/src/strands/types.py.
Model Provider Surface
Both language targets expose a family of model providers behind a consistent abstract base. The Python side uses lazy loading so that optional provider dependencies are not imported until the user actually instantiates that provider. Source: strands-py/src/strands/models/__init__.py.
Python Provider Catalog
| Provider class | Module | Lazy loaded |
|---|---|---|
BedrockModel | bedrock.py | Eager |
AnthropicModel | anthropic.py | Yes (via __getattr__) |
GeminiModel | gemini.py | Yes |
LiteLLMModel | litellm.py | Yes |
LlamaAPIModel | llamaapi.py | Yes |
LlamaCppModel | llamacpp.py | Yes |
MistralModel | mistral.py | Yes |
OllamaModel | ollama.py | Yes |
OpenAIModel | openai.py | Yes |
Model and BaseModelConfig are exported eagerly. Source: strands-py/src/strands/models/__init__.py.
TypeScript Provider Catalog
The TS SDK mirrors the same model-provider philosophy. The Bedrock provider, for example, imports @aws-sdk/client-bedrock-runtime and reuses shared streaming types such as CitationsDelta, ReasoningContentDelta, and Usage. It also re-exports the common BaseModelConfig and StreamOptions from a single source of truth. Source: strands-ts/src/models/bedrock.ts, strands-ts/src/models/model.ts.
Streaming Event Vocabulary
The TS SDK defines a stream event vocabulary that the Python WASM package mirrors through its generated bindings. Key event shapes include:
| Type | Purpose |
|---|---|
ToolUseInputDelta | Incremental tool input being generated. |
ReasoningContentDelta | Incremental reasoning/thinking content. |
CitationsDelta | Citations attached to generated content. |
Usage | Input, output, total, and cache token counts. |
Source: strands-ts/src/models/streaming.ts.
Provider Implementation Patterns
Each provider implements the same loop, with provider-specific request formatting and error handling. The OpenAI provider formats an OpenAI-compatible chat streaming request, the OpenAI Responses provider reuses the native input_tokens.count endpoint when use_native_token_count is enabled, and the Mistral provider supports both streaming and non-streaming code paths. Source: strands-py/src/strands/models/openai.py, strands-py/src/strands/models/openai_responses.py, strands-py/src/strands/models/mistral.py.
Documentation Site
The site/ package is the user-facing documentation hub. It is built with Astro 6 and Starlight 0.38, uses TypeDoc 0.28 for TypeScript reference generation, and uses pydoc-markdown for the Python reference. The package script surface shows how the docs are tied to both SDKs:
| Script | Effect |
|---|---|
build | astro build |
build:all | sdk:clone + sdk:generate + build |
sdk:clone | Clones both SDK repositories locally. |
sdk:generate:py | Runs pydoc-markdown (via uv or pip). |
sdk:generate:ts | Runs TypeDoc on the TypeScript SDK. |
sdk:sync | sdk:clone + sdk:generate + npm install. |
routes:update | Updates the known-routes index used by the site. |
typecheck / test / format | Standard maintenance scripts. |
Source: site/package.json.
Governance and Design Process
Two governance documents shape the monorepo's evolution.
Design Proposals (`designs/`)
A design document is required for new major features affecting multiple parts of the SDK, breaking changes to existing APIs, architectural changes requiring design discussion, large contributions, and features that introduce new concepts. Bug fixes, small improvements, documentation updates, and new extensions in a contributor's own repository are explicitly excluded. The submission flow is:
- Check the roadmap.
- Create a branch.
- Add
designs/NNNN-feature-name.mdusing the provided template. - Submit a pull request.
- Iterate on feedback.
- Get approval and merge.
- Reference the design from the implementation PR.
The template captures Status, Date, Issue, Context, Decision, Developer Experience, Alternatives Considered, Consequences, and Willingness to Implement. At the time of the source files reviewed, "No designs have been accepted yet." Source: designs/README.md.
Team Doctrine (`team/`)
The team/ directory contains the long-lived principles that apply to all SDK work:
| Document | Purpose |
|---|---|
TENETS.md | Core principles guiding SDK design. |
DECISIONS.md | Record of design and API decisions with rationale. |
API_BAR_RAISING.md | Process for reviewing and approving API changes. |
AGENT_GUIDELINES.md | Conventions for AI agents operating on the repos. |
When a contribution results in a new decision that could guide future work, the contribution should add it to DECISIONS.md. Source: team/README.md.
End-to-End Developer Workflow
The first-time developer experience flows through the monorepo's npm run dev -- bootstrap command, which is intentionally exhaustive so that "if this command doesn't enable development out of the box, file an issue." Source: strands-wasm/README.md.
graph TD
A[Clone repository] --> B[npm install]
B --> C[npm run dev -- bootstrap]
C --> D[Toolchains installed]
C --> E[strandly linked to PATH]
C --> F[Type bindings generated]
C --> G[All layers built]
C --> H[strands-py-wasm installed]
C --> I[All tests run]
D --> J[Ready to develop]
E --> J
F --> J
G --> J
H --> J
I --> JSource: strands-wasm/README.md.
Prerequisites are intentionally minimal: Node.js 20+ and Python 3.10+. Source: strands-wasm/README.md.
Configuration and Customization Points
The monorepo is configurable in several places, each owned by a different package.
| Layer | Configuration mechanism | Source |
|---|---|---|
| TypeScript model providers | BaseModelConfig (modelId, maxTokens, temperature, topP, contextWindowLimit). contextWindowLimit is auto-resolved from a built-in lookup table when not explicitly set, and re-resolved when modelId changes via updateConfig(). | strands-ts/src/models/model.ts |
| Python provider selection | Lazy import via __getattr__ so unused providers do not impose dependency costs. | strands-py/src/strands/models/__init__.py |
| WASM Python public surface | types.py drops stream-only primitives (Datetime, Duration, Error, InputStream, OutputStream, Pollable) and adds curated union types (ModelInput, ConversationManagerInput, VendedToolInput, VendedPluginInput). | strands-py-wasm/src/strands/types.py |
| OpenAI Responses token counting | use_native_token_count in provider config toggles between native input_tokens.count and fallback estimation. | strands-py/src/strands/models/openai_responses.py |
| Mistral tool choice | tool_choice is accepted but currently ignored for that provider (with a runtime warning). | strands-py/src/strands/models/mistral.py |
| Documentation site | site/package.json scripts (sdk:clone, sdk:generate:py, sdk:generate:ts, routes:update) drive which SDKs are referenced and how. | site/package.json |
Common Failure Modes and Pitfalls
These are the failure modes that can be observed from the source files alone; they are not invented, only described from evidence in the code.
- Optional provider dependencies. The Python
models/__init__.pylazy-loads every provider exceptBedrockModel. If a user instantiates, e.g.,AnthropicModelwithout that provider's package installed, the lazy import will fail at first use. Source: strands-py/src/strands/models/__init__.py. - Native token counting fallback. The OpenAI Responses provider attempts a native count when
use_native_token_countis true, but on any exception it logs a debug message and falls back to estimation. Callers must not assume native counts are always returned. Source: strands-py/src/strands/models/openai_responses.py. - Ignored
tool_choice. The Mistral provider acceptstool_choicefor interface consistency but explicitly does not honor it. Relying on it for Mistral will silently misbehave. Source: strands-py/src/strands/models/mistral.py. - Auto-populated
contextWindowLimit. The TS base config notes that explicitly setcontextWindowLimitis preserved whenmodelIdchanges, while auto-populated values are re-resolved. Code that mutates the model ID dynamically should be aware of this. Source: strands-ts/src/models/model.ts. - Design gating. New major features require an accepted design document. A pull request that adds cross-cutting functionality without a corresponding accepted design is likely to be sent back to the proposal stage. Source: designs/README.md.
- Bootstrap dependency. The
bootstrapscript is the single source of truth for first-time setup. If it does not yield a working developer environment, the project's own documentation asks contributors to file an issue rather than improvise. Source: strands-wasm/README.md.
Community-Reported Gaps and Roadmap Signals
Several community requests are worth calling out here because they directly map to monorepo decisions:
- TypeScript/Node SDK (#156) — Already addressed by
strands-ts, though users continue to discuss frontend, backend, and IaC (CDK) TypeScript workflows. - Go SDK (#616) and Java SDK (#240) — Both are open requests. Neither has a corresponding package in the monorepo today; both would require new top-level directories analogous to
strands-pyandstrands-ts. - Agent Skills (#1181) — The generated
strands-py-wasmsymbols already includeSkillSource, and theVendedPluginInputunion includesAgentSkills, indicating the WASM-bridged SDK has begun to expose a skills surface. - AG-UI Protocol (#140) — Community proposal to map Strands events to the AG-UI protocol. The streaming event vocabulary in
strands-ts/src/models/streaming.tsis the natural integration point. - Latest release signal — "Python WASM v0.0.1 / Initial release of strands-agents-wasm" indicates the WASM bridge is the most recent forward step in the monorepo.
Source: community_context provided in the query; cross-references via strands-py-wasm/src/strands/types.py and strands-py-wasm/src/strands/_generated/__init__.py.
See Also
- strands-py/src/strands/models/__init__.py — Python model provider registry and lazy loading.
- strands-ts/src/models/model.ts — TypeScript base model configuration and streaming options.
- strands-wasm/README.md — WASM build pipeline and WIT contract reference.
- strands-py-wasm/src/strands/types.py — Curated Python re-exports of the WASM-bridged surface.
- designs/README.md — Design proposal process and template.
- team/README.md — Team doctrine, tenets, and decisions log.
Source: https://github.com/strands-agents/harness-sdk / Human Manual
Agent Loop, Tools & Hooks
Related topics: Monorepo Architecture & SDKs Overview, Model Providers & Multi-Agent Patterns
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Monorepo Architecture & SDKs Overview, Model Providers & Multi-Agent Patterns
Agent Loop, Tools & Hooks
Overview
The Agent Loop, Tools & Hooks is the core execution model that makes Strands Agents a model-driven SDK for building and running AI agents. Rather than prescribing a rigid graph or state machine, Strands keeps the agent loop lightweight, hands the model control over tool selection, and exposes lifecycle hooks so developers can observe, customize, and integrate around each turn of the loop.
Strands Agents is delivered as a monorepo containing multiple SDKs that all converge on the same conceptual model:
| Package | Path | Purpose |
|---|---|---|
| Python SDK | strands-py/ | Agent loop, model providers, tools (PyPI: strands-agents) |
| TypeScript SDK | strands-ts/ | Agent loop, model providers, tools (npm: @strands/agents) |
| WebAssembly bindings | strands-wasm/ + strands-py-wasm/ | Run the TypeScript agent from Python via WASM |
| Developer CLI | strandly/ | Local builds, codegen, workspace tooling |
| Documentation site | site/ | Astro/Starlight site at strandsagents.com |
| Design proposals | designs/ | RFC-style documents for significant changes |
| Team docs | team/ | Tenets, decisions, API review process |
Source: README.md
The high-level tagline — "simple agent loop that just works and is fully customizable" — is the design intent behind this subsystem. Source: strands-py/README.md
Source: https://github.com/strands-agents/harness-sdk / Human Manual
Model Providers & Multi-Agent Patterns
Related topics: Agent Loop, Tools & Hooks, Plugins, Bidirectional Streaming & WASM Interop
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Agent Loop, Tools & Hooks, Plugins, Bidirectional Streaming & WASM Interop
Model Providers & Multi-Agent Patterns
Overview
Strands Agents is a model-driven SDK for building and running AI agents. Its two most consequential architectural commitments are: (1) a model-agnostic provider layer that lets the same agent loop drive Bedrock, Anthropic, OpenAI, Gemini, Mistral, Writer, LiteLLM, LlamaAPI, LlamaCpp, Ollama, and SageMaker, and (2) a multi-agent orchestration layer that composes those agents into Graph and Swarm topologies. This page documents both layers, the streaming event contract that ties them together, and the multi-language surface (Python, TypeScript, and the WASM bridge) that exposes them.
The provider layer is declared in strands-py/src/strands/models/__init__.py as a package of "an abstract base Model class along with concrete implementations for specific providers," and it uses lazy import via __getattr__ so optional provider SDKs are only loaded when actually requested. The TypeScript counterpart is declared in strands-ts/src/models/model.ts through the BaseModelConfig interface and the StreamOptions shape, ensuring provider parity across languages.
The multi-agent capabilities (Graph and Swarm) are advertised as "Advanced Capabilities" in the top-level README and as "Multi-Agent Orchestration" in the TypeScript README, and are exposed across the Python, TypeScript, and WASM boundaries through the type set in strands-py-wasm/src/strands/_generated/__init__.py (e.g. SwarmConfig).
The Model-Provider Layer
Provider Package Layout
strands-py/src/strands/models/__init__.py lists the model module's public surface and implements lazy loading for every non-default provider:
# strands-py/src/strands/models/__init__.py
from . import bedrock, model
from .bedrock import BedrockModel
from .model import BaseModelConfig, CacheConfig, CacheToolsConfig, Model
__all__ = [
"bedrock",
"model",
"BaseModelConfig",
"BedrockModel",
"CacheConfig",
"CacheToolsConfig",
"Model",
]
def __getattr__(name: str) -> Any:
if name == "AnthropicModel":
from .anthropic import AnthropicModel
return AnthropicModel
# ... GeminiModel, LiteLLMModel, LlamaAPIModel, LlamaCppModel,
# MistralModel, OllamaModel, OpenAIModel, ... lazily loaded
Source: strands-py/src/strands/models/__init__.py
This pattern is important operationally: a project that only needs Bedrock never imports the Anthropic, Gemini, or Mistral SDKs, keeping cold-start times and dependency graphs lean. Each provider module follows a uniform contract (format_request, format_chunk, stream, _handle_non_streaming_response) so the agent loop can be provider-blind.
Provider Inventory
The table below summarizes the providers shipped in the Python SDK, the module that implements them, and notable configuration behaviors visible in the source.
| Provider | Module | Stream Toggle | Tool Choice | Notable Behavior |
|---|---|---|---|---|
| Amazon Bedrock | strands-py/src/strands/models/bedrock.py | config["stream"] (default True) | Honored | Default provider, requires model_id in us-west-2 per strands-py/README.md |
| Anthropic | strands-py/src/strands/models/anthropic.py | Honored | Honored | Direct Anthropic API |
| OpenAI (Chat Completions) | strands-py/src/strands/models/openai.py | Honored | Honored | _format_system_messages and _format_regular_messages produce OpenAI-compatible arrays |
| OpenAI (Responses) | strands-py/src/strands/models/openai_responses.py | Honored | Honored | Separate module for the new Responses API |
| Gemini | strands-py/src/strands/models/gemini.py | Honored | Honored | Google GenAI |
| Mistral | strands-py/src/strands/models/mistral.py | config.get("stream", True) | Ignored with warn_on_tool_choice_not_supported | Raises ModelThrottledException on rate limits |
| Writer | strands-py/src/strands/models/writer.py | Always streaming in _stream | Ignored with warning | Renames model_id → model; raises KeyError if not set; tools key omitted when empty |
| LiteLLM | strands-py/src/strands/models/litellm.py | Honored | Honored | Routes through LiteLLM to 100+ providers |
| LlamaAPI | strands-py/src/strands/models/llamaapi.py | Honored | Honored | Hosted Llama API |
| LlamaCpp | strands-py/src/strands/models/llamacpp.py | Honored | Honored | Local in-process inference |
| Ollama | strands-py/src/strands/models/ollama.py | Honored | Honored | Local Ollama daemon |
| SageMaker | strands-py/src/strands/models/sagemaker.py | Honored | Honored | Self-hosted SageMaker endpoints |
Source: strands-py/src/strands/models/mistral.py, strands-py/src/strands/models/writer.py, strands-py/src/strands/models/openai.py
Common Configuration Surface
strands-py/src/strands/models/model.py defines BaseModelConfig, which every provider extends. The TypeScript equivalent lives in strands-ts/src/models/model.ts as the BaseModelConfig interface:
// strands-ts/src/models/model.ts
export interface BaseModelConfig {
modelId?: string
maxTokens?: number
temperature?: number
topP?: number
contextWindowLimit?: number
}
Source: strands-ts/src/models/model.ts
contextWindowLimit has special semantics in the TypeScript layer: when not provided, it is resolved from a built-in lookup table keyed by modelId, and is re-resolved automatically after updateConfig({ modelId }) if the value was initially auto-populated. This auto-resolution behavior is implemented to keep cache- and truncation-related code free of provider-specific branching.
Streaming Event Contract
Every provider funnels into the same chunk vocabulary. strands-ts/src/models/streaming.ts documents the wire-level types that both the Python and TypeScript layers must emit:
| Chunk Type | Purpose |
|---|---|
messageStart | Begins an assistant turn; sets role: "assistant" |
contentBlockStart | Opens a content block (text or tool use) |
contentBlockDelta | Incremental text or tool input |
contentBlockStop | Closes a content block |
messageStop | Ends an assistant turn |
toolUseStart / toolUseInputDelta / toolUseStop | Tool-use lifecycle |
reasoningContentDelta | Reasoning / thinking tokens (text, signature, redacted) |
citationsDelta | Citations linking generated content to source locations |
usage | Input/output/cache token accounting |
Source: strands-ts/src/models/streaming.ts
The Python providers emit matching chunk types via format_chunk. For example, the Mistral provider emits {"chunk_type": "message_start"} and then translates streamed choices into content_block_delta events, accumulating text in accumulated_text and tool calls in a dict[str, list[Any]] keyed by tool id. Source: strands-py/src/strands/models/mistral.py
The Writer provider follows the same shape: format_chunk({"chunk_type": "message_start"}) then format_chunk({"chunk_type": "content_block_start", "data_type": "text"}) followed by per-token content_block_delta events for choice.delta.content and tool-call deltas for choice.delta.tool_calls. Source: strands-py/src/strands/models/writer.py
Provider Streaming Flow
graph TD
A[Agent Loop] --> B[Model.stream]
B --> C[format_request]
C --> D{stream flag}
D -->|True| E[Provider stream API]
D -->|False| F[Non-streaming API + _handle_non_streaming_response]
E --> G[format_chunk per event]
F --> G
G --> H[Standardized StreamEvent]
H --> I[Agent consumes via async iterator]
I --> J[Tool dispatch, if toolUse present]Source: strands-py/src/strands/models/mistral.py, strands-py/src/strands/models/writer.py
Provider Quirks and Failure Modes
Two cross-provider quirks are worth flagging because they trip up new users:
tool_choiceis silently ignored on some providers. Mistral and Writer accept the parameter for interface consistency but pass it throughwarn_on_tool_choice_not_supported(tool_choice)and discard the value. Source: strands-py/src/strands/models/mistral.py, strands-py/src/strands/models/writer.py
- Throttling is normalized to
ModelThrottledException. Both Mistral and Writer translate provider-specific rate-limit errors (mistralai.RateLimitError,writerai.RateLimitError) into a single SDK exception so retry/circuit-breaker code in the agent loop can be provider-agnostic. Source: strands-py/src/strands/models/mistral.py, strands-py/src/strands/models/writer.py
- Empty
toolslists are dropped. Writer raises aKeyErrorifmodel_idis not set, and explicitly omits thetoolskey from the request whentool_specsis empty, because the Writer API rejects empty tools arrays. Source: strands-py/src/strands/models/writer.py
TypeScript Provider Parity
The TypeScript SDK follows the same model-agnostic philosophy. The default BedrockModel is the canonical first-class provider, with OpenAI listed as supported and an extension point for custom providers (advertised in strands-ts/README.md):
import { Agent, BedrockModel } from '@strands-agents/sdk'
const agent = new Agent({
model: new BedrockModel({ region: 'us-east-1' }),
tools: [notebook],
})
Source: strands-ts/README.md, strands-ts/src/vended-tools/notebook/README.md
The TypeScript BaseModelConfig includes an explicit contextWindowLimit field whose default behavior (auto-resolved from a lookup table, re-resolved on modelId change unless explicitly set) is documented in the JSDoc and designed to let conversation managers pick a strategy without per-provider branching. Source: strands-ts/src/models/model.ts
Multi-Agent Patterns
Pattern Catalog
The Strands SDK ships two multi-agent orchestration patterns, both surfaced across Python, TypeScript, and the WASM surface:
| Pattern | Best For | Surface Name |
|---|---|---|
| Graph | Explicit, deterministic routing between agents with typed edges | Exposed via Python, TypeScript, and strands-py-wasm |
| Swarm | Autonomous, emergent delegation between peer agents | Exposed as SwarmConfig in the WASM type set |
Source: strands-py/README.md, strands-ts/README.md, strands-py-wasm/src/strands/_generated/__init__.py
The SwarmConfig symbol appears in the WASM public types generated for the Python↔TypeScript bridge, indicating that Swarm is treated as a first-class orchestration primitive that must round-trip through the WIT contract. Source: strands-py-wasm/src/strands/_generated/__init__.py
How the Multi-Agent Loop Reuses the Provider Layer
Every agent in a Graph or Swarm is itself a Strands Agent, so it can target any provider in the table above. This means a single multi-agent system can mix providers — for example, a routing agent on Bedrock, a research agent on OpenAI, and a code-generation agent on a local LlamaCpp instance — without any change to the orchestration code. The provider-agnosticism of the Model base class is what makes that composition possible. Source: strands-py/src/strands/models/__init__.py
graph TD
User[User Request] --> Router{Router Agent}
Router -->|research| Research[Research Agent<br/>OpenAI]
Router -->|code| Code[Code Agent<br/>LlamaCpp local]
Router -->|summarize| Summary[Summary Agent<br/>Bedrock]
Research --> Synth[Synthesizer Agent<br/>Bedrock]
Code --> Synth
Summary --> Synth
Synth --> UserThe diagram is a representative Graph topology; concrete edge conditions are authored by the application, not the SDK. Source: strands-py/README.md, strands-ts/README.md
Tool and Plugin Reuse in Multi-Agent Setups
Multi-agent setups benefit from the same plugin/tool system as single agents. Vended tools (BashTool, FileEditorTool, HttpRequestTool, NotebookTool) and vended plugins (AgentSkills, ContextOffloader) are re-exported by the WASM surface via type unions in strands-py-wasm/src/strands/types.py:
VendedToolInput = VendedTool | BashTool | FileEditorTool | HttpRequestTool | NotebookTool
VendedPluginInput = VendedPlugin | AgentSkills | ContextOffloader
Source: strands-py-wasm/src/strands/types.py
A community request, [FEATURE] Add support for skills (#1181), asks for first-class Agent Skills support to load relevant knowledge files into context per task. The AgentSkills plugin already exists in the WASM type surface, so the request maps onto plugin wiring rather than a new primitive. Source: strands-py-wasm/src/strands/types.py
Streaming and Conversation Management
Both single-agent and multi-agent invocations share the same streaming event contract documented in strands-ts/src/models/streaming.ts. Three event categories matter most for multi-agent systems:
- Reasoning deltas —
reasoningContentDeltacarries incremental text, signature, and redacted-reasoning bytes. This is the type multi-agent routers surface to expose an agent's intermediate deliberation to the parent. - Tool-use deltas —
toolUseInputDeltastreams partial JSON for tool inputs, which is critical when an agent invokes a long-running tool that another agent should be able to observe. - Usage deltas —
UsagereportsinputTokens,outputTokens,totalTokens, plus cache-related metrics, enabling fair cost accounting when one parent agent orchestrates many children.
Source: strands-ts/src/models/streaming.ts
On the Python side, conversation managers are exposed as the union SlidingWindowConversationManager | SummarizingConversationManager, and the model-agnostic input is ModelConfig | BedrockModel | AnthropicModel | OpenaiModel | GoogleModel | CustomModel. These unions make the orchestration surface fully provider-agnostic. Source: strands-py-wasm/src/strands/types.py
The WASM Bridge and Cross-Language Providers
The Python WASM build (strands-py-wasm) is a WebAssembly packaging of the TypeScript SDK. The contract is defined by wit/agent.wit and the type set in strands-py-wasm/src/strands/_generated/__init__.py:
- Exports (TypeScript implements, Python calls): the
apiinterface, including agent construction, streaming, and conversation management. All model provider HTTP calls — Bedrock, Anthropic, OpenAI, Gemini — happen inside the WASM guest. - Imports (Python implements, TypeScript calls back into):
tool-providerfor executing Python-defined tools, andhost-logfor routing log entries to Python's logging framework.
Source: strands-wasm/README.md
This means that when running strands-py-wasm, the model-provider HTTP calls are made by the TypeScript code compiled into strands-agent.wasm, and Python only sees streamed events through the api export. For a multi-agent Python application that imports the WASM package, every child agent's provider is effectively a TypeScript-backed provider, but the Python orchestration code is unaware of that boundary. Source: strands-wasm/README.md
The latest release of strands-agents-wasm is v0.0.1 (initial release), per the community context.
Community-Driven Direction
Several community issues are directly relevant to the provider and multi-agent story:
- #156 Add TypeScript/JavaScript/NodeJS SDK — Resolved by the existence of the
strands-tspackage and thestrands-py-wasmbridge, both of which expose the same provider and multi-agent surfaces. - #616 Go SDK — Not yet on the roadmap. The WASM bridge demonstrates that the provider contract is portable enough to retarget, so a future Go SDK is plausible but unannounced.
- #240 Java SDK — Same status as Go; no announced work, but the type set in
strands-py-wasm/src/strands/_generated/__init__.pyis a candidate seed for cross-language codegen. - #1181 Agent Skills — The
AgentSkillsplugin already appears in the WASM type surface; further work is integration rather than core infrastructure. - #140 AG-UI protocol — A proposal to map Strands stream events to the AG-UI protocol. The standardized event vocabulary in
strands-ts/src/models/streaming.ts(and mirrored by Pythonformat_chunk) is the natural mapping source.
Source: strands-py-wasm/src/strands/_generated/__init__.py, strands-ts/src/models/streaming.ts
Design and Contribution Workflow
Significant changes to the provider or multi-agent layers are expected to follow the design process described in designs/README.md. The repository uses an RFC-style template with Status, Context, Decision, Developer Experience, Alternatives Considered, Consequences, and Willingness to Implement sections. As of the most recent README snapshot, no designs have been accepted yet, so all multi-agent and provider work is currently shaped in code rather than in merged design documents. Source: designs/README.md
The team/ directory houses internal guidance: TENETS.md (core SDK principles), DECISIONS.md (rationale records), API_BAR_RAISING.md (the API review process), and AGENT_GUIDELINES.md (conventions for AI agents operating on the repo). Source: team/README.md
See Also
- Quickstart and overview:
strands-py/README.md,strands-ts/README.md - Provider internals:
strands-py/src/strands/models/*.py,strands-ts/src/models/model.ts - Streaming contract:
strands-ts/src/models/streaming.ts - WASM type surface:
strands-py-wasm/src/strands/_generated/__init__.py,strands-py-wasm/src/strands/types.py - WASM architecture:
strands-wasm/README.md - Design process:
designs/README.md,team/README.md - Vended tools used by multi-agent setups:
strands-ts/src/vended-tools/notebook/README.md
Source: https://github.com/strands-agents/harness-sdk / Human Manual
Plugins, Bidirectional Streaming & WASM Interop
Related topics: Monorepo Architecture & SDKs Overview, Model Providers & Multi-Agent Patterns
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Monorepo Architecture & SDKs Overview, Model Providers & Multi-Agent Patterns
Plugins, Bidirectional Streaming & WASM Interop
The Strands Agents SDK exposes three closely related extensibility surfaces:
- A vended plugin system (Skills, Context Offloader, Steering) that wraps reusable agent behaviors into a single lifecycle API.
- A bidirectional streaming (bidi) subsystem under
strands.experimental.bidifor realtime, multimodal model sessions. - A WebAssembly (WASM) interop layer (
strands-wasm,strands-py-wasm,strands-ts) that compiles the TypeScript runtime into a WASM component embedded inside the Python host.
This page describes the public shape of those subsystems, how they fit together, and how the WIT contract defines the boundary between the WASM guest and the Python host.
Source: https://github.com/strands-agents/harness-sdk / Human Manual
Doramagic Pitfall Log
Source-linked risks stay visible on the manual page so the preview does not read like a recommendation.
May increase setup, validation, or first-run risk for the user.
Developers may expose sensitive permissions or credentials: [BUG] CacheConfig(strategy="auto") does not detect Claude models when using ARN-based inference profiles
May increase setup, validation, or first-run risk for the user.
May increase setup, validation, or first-run risk for the user.
Doramagic Pitfall Log
Found 30 structured pitfall item(s), including 3 high/blocking item(s). Top priority: Installation risk - Installation risk requires verification.
1. Installation risk: Installation risk requires verification
- Severity: high
- Finding: Project evidence flags a installation risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: community_evidence:github | https://github.com/strands-agents/harness-sdk/issues/2748
2. Security or permission risk: Security or permission risk requires verification
- Severity: high
- Finding: Developers should check this security_permissions risk before relying on the project: [BUG] CacheConfig(strategy="auto") does not detect Claude models when using ARN-based inference profiles
- User impact: Developers may expose sensitive permissions or credentials: [BUG] CacheConfig(strategy="auto") does not detect Claude models when using ARN-based inference profiles
- Recommended check: Before packaging this project, run the relevant install/config/quickstart check for: [BUG] CacheConfig(strategy="auto") does not detect Claude models when using ARN-based inference profiles. Context: Observed when using python
- Evidence: failure_mode_cluster:github_issue | https://github.com/strands-agents/harness-sdk/issues/2601
3. Security or permission risk: Security or permission risk requires verification
- Severity: high
- Finding: Project evidence flags a security or permission risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: community_evidence:github | https://github.com/strands-agents/harness-sdk/issues/482
4. Identity risk: Identity risk requires verification
- Severity: medium
- Finding: Project evidence flags a identity risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: identity.distribution | https://github.com/strands-agents/harness-sdk
5. Installation risk: Installation risk requires verification
- Severity: medium
- Finding: Developers should check this installation risk before relying on the project: [BUG] Gemini rejects tool results with multiple same-format images: duplicate displayName in function_response.parts (400 INVALID_ARGUMENT)
- User impact: Developers may fail before the first successful local run: [BUG] Gemini rejects tool results with multiple same-format images: duplicate displayName in function_response.parts (400 INVALID_ARGUMENT)
- Recommended check: Before packaging this project, run the relevant install/config/quickstart check for: [BUG] Gemini rejects tool results with multiple same-format images: duplicate displayName in function_response.parts (400 INVALID_ARGUMENT). Context: Observed when using node, docker, macos, linux
- Evidence: failure_mode_cluster:github_issue | https://github.com/strands-agents/harness-sdk/issues/2748
6. Installation risk: Installation risk requires verification
- Severity: medium
- Finding: Developers should check this installation risk before relying on the project: [BUG] OpenAIModel tool message content sent as array instead of string breaks OpenAI-compatible endpoints (e.g., Kimi K2.5)
- User impact: Developers may fail before the first successful local run: [BUG] OpenAIModel tool message content sent as array instead of string breaks OpenAI-compatible endpoints (e.g., Kimi K2.5)
- Recommended check: Before packaging this project, run the relevant install/config/quickstart check for: [BUG] OpenAIModel tool message content sent as array instead of string breaks OpenAI-compatible endpoints (e.g., Kimi K2.5). Context: Observed when using python, macos
- Evidence: failure_mode_cluster:github_issue | https://github.com/strands-agents/harness-sdk/issues/1696
7. Installation risk: Installation risk requires verification
- Severity: medium
- Finding: Developers should check this installation risk before relying on the project: python/v1.41.0
- User impact: Upgrade or migration may change expected behavior: python/v1.41.0
- Recommended check: Before packaging this project, run the relevant install/config/quickstart check for: python/v1.41.0. Context: Observed when using python
- Evidence: failure_mode_cluster:github_release | https://github.com/strands-agents/harness-sdk/releases/tag/python/v1.41.0
8. Installation risk: Installation risk requires verification
- Severity: medium
- Finding: Developers should check this installation risk before relying on the project: v1.41.0
- User impact: Upgrade or migration may change expected behavior: v1.41.0
- Recommended check: Before packaging this project, run the relevant install/config/quickstart check for: v1.41.0. Context: Observed when using python
- Evidence: failure_mode_cluster:github_release | https://github.com/strands-agents/harness-sdk/releases/tag/v1.41.0
9. Installation risk: Installation risk requires verification
- Severity: medium
- Finding: Project evidence flags a installation risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: community_evidence:github | https://github.com/strands-agents/harness-sdk/issues/1696
10. Installation risk: Installation risk requires verification
- Severity: medium
- Finding: Project evidence flags a installation risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: community_evidence:github | https://github.com/strands-agents/harness-sdk/issues/2614
11. Installation risk: Installation risk requires verification
- Severity: medium
- Finding: Project evidence flags a installation risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: community_evidence:github | https://github.com/strands-agents/harness-sdk/issues/2421
12. Configuration risk: Configuration risk requires verification
- Severity: medium
- Finding: Developers should check this configuration risk before relying on the project: [FEATURE] Support Managed Bedrock Knowledge Bases for Memory Manager
- User impact: Developers may misconfigure credentials, environment, or host setup: [FEATURE] Support Managed Bedrock Knowledge Bases for Memory Manager
- Recommended check: Before packaging this project, run the relevant install/config/quickstart check for: [FEATURE] Support Managed Bedrock Knowledge Bases for Memory Manager. Context: Source discussion did not expose a precise runtime context.
- Evidence: failure_mode_cluster:github_issue | https://github.com/strands-agents/harness-sdk/issues/2880
Source: Doramagic discovery, validation, and Project Pack records
Community Discussion Evidence
These external discussion links are review inputs, not standalone proof that the project is production-ready.
Count of project-level external discussion links exposed on this manual page.
Open the linked issues or discussions before treating the pack as ready for your environment.
Community Discussion Evidence
Doramagic exposes project-level community discussion separately from official documentation. Review these links before using harness-sdk with real data or production workflows.
- Python middleware: add interrupt source field to distinguish middleware- - github / github_issue
- [[BUG] Gemini rejects tool results with multiple same-format images: dupl](https://github.com/strands-agents/harness-sdk/issues/2748) - github / github_issue
- [[FEATURE] Support Managed Bedrock Knowledge Bases for Memory Manager](https://github.com/strands-agents/harness-sdk/issues/2880) - github / github_issue
- [[FEATURE] Support for multiple MCP servers (and loading from config file](https://github.com/strands-agents/harness-sdk/issues/482) - github / github_issue
- [[BUG] CacheConfig(strategy="auto") does not detect Claude models when us](https://github.com/strands-agents/harness-sdk/issues/2601) - github / github_issue
- [[FEATURE] Support audio input for standard Agent (Specially using Bedroc](https://github.com/strands-agents/harness-sdk/issues/2614) - github / github_issue
- [[WASM] Python SDK - Gaps and Limitations](https://github.com/strands-agents/harness-sdk/issues/2421) - github / github_issue
- [[WASM] MCP tools](https://github.com/strands-agents/harness-sdk/issues/2456) - github / github_issue
- [[BUG] OpenAIModel tool message content sent as array instead of string b](https://github.com/strands-agents/harness-sdk/issues/1696) - github / github_issue
- typescript/v1.6.0 - github / github_release
- python/v1.44.0 - github / github_release
- typescript/v1.5.0 - github / github_release
Source: Project Pack community evidence and pitfall evidence