Skip to content

harness-sdk

v1.23.0 Feature

This release adds 6 notable features for engineering teams evaluating rollout.

✓ No known CVEs patched
Read the diff → Tool health → What is this tool? →

✓ No known CVEs patched in this version

Topics

agentic agentic-ai agents ai anthropic autonomous-agents
+13 more
bedrock genai litellm llama llm machine-learning mcp multi-agent-systems ollama openai opentelemetry python strands-agents

Summary

AI summary

Broad release touches Major Bug Fixes, Major Features, HookProvider, and agent.

Full changelog

Major Features

Configurable Retry Strategy for Model Calls - PR#1424

Agents now support customizable retry behavior when handling model throttling exceptions. The new ModelRetryStrategy class allows you to configure maximum retry attempts, initial delay, and maximum delay, replacing the previously hardcoded retry logic.

 from strands import Agent, ModelRetryStrategy
 
 agent = Agent(
     model="anthropic.claude-3-sonnet",
     retry_strategy=ModelRetryStrategy(
         max_attempts=3,
         initial_delay=2,
         max_delay=60
     )
 )

Model Response Steering - PR#1429

Steering handlers can now intercept and guide model responses through the new steer_after_model() method. This enables validation of model outputs, enforcement of required tool usage, and conversation flow control based on model responses before the agent completes.

 from strands.experimental.steering import Guide, Proceed, SteeringHandler
 
 class ForceToolUsageHandler(SteeringHandler):
     def __init__(self, required_tool: str):
         super().__init__()
         self.required_tool = required_tool
 
     async def steer_after_model(self, *, agent, message, stop_reason, **kwargs):
         if stop_reason != "end_turn":
             return Proceed(reason="Model still processing")
 
         # Check if required tool was used
         for block in message.get("content", []):
             if "toolUse" in block and block["toolUse"].get("name") == self.required_tool:
                 return Proceed(reason="Required tool was used")
 
         # Force tool usage
         return Guide(reason=f"You MUST use the {self.required_tool} tool.")
 
 agent = Agent(tools=[log_tool], hooks=[ForceToolUsageHandler("log_activity")])

Input Messages in BeforeInvocationEvent - PR#1474

The BeforeInvocationEvent hook now exposes the input messages through a new messages parameter, enabling preprocessing, guardrails, and filters to run before the agent processes user input.

 from strands import Agent
 from strands.hooks import HookProvider, BeforeInvocationEvent
 
 class PreprocessingHook(HookProvider):
     def register_hooks(self, registry):
         registry.add_callback(BeforeInvocationEvent, self.preprocess)
     
     def preprocess(self, event):
         # Access input messages for preprocessing
         messages = event.messages
         # Apply guardrails or filters here
         pass
 
 agent = Agent(hooks=[PreprocessingHook()])

Nova Sonic 2 Support for BidiAgent - PR#1476

BidiAgent now supports Amazon Nova Sonic v2 models with enhanced features including the turn_taking parameter and improved text input handling for bidirectional voice conversations.

 from strands.experimental.bidi.models import BidiNovaSonicModel
 from strands.experimental.bidi import BidiAgent
 
 model = BidiNovaSonicModel(model_id="us.amazon.nova-sonic-v2:0")
 agent = BidiAgent(model=model)

Graph Interrupts from Hooks - PR#1478

Graph nodes can now be interrupted from BeforeNodeCallEvent hooks, enabling approval workflows and human-in-the-loop validation before specific agents execute in multi-agent graphs.

 from strands import Agent
 from strands.hooks import HookProvider, BeforeNodeCallEvent
 from strands.multiagent import GraphBuilder, Status
 
 class ApprovalHook(HookProvider):
     def register_hooks(self, registry):
         registry.add_callback(BeforeNodeCallEvent, self.approve)
 
     def approve(self, event):
         if event.node_id == "info_agent":
             return
 
         response = event.interrupt("my_interrupt", reason=f"{event.node_id} needs approval")
         if response != "APPROVE":
             event.cancel_node = "node rejected"
 
 builder = GraphBuilder()
 builder.add_node(info_agent, "info_agent")
 builder.add_node(weather_agent, "weather_agent")
 builder.add_edge("info_agent", "weather_agent")
 builder.set_hook_providers([ApprovalHook()])
 graph = builder.build()
 
 result = graph("What is the weather?")
 while result.status == Status.INTERRUPTED:
     # Handle interrupts and resume with responses
     result = graph(interrupt_responses)

Multiagent Hook Events Graduated - PR#1498

Multiagent hook events (BeforeNodeCallEvent, AfterNodeCallEvent) have been promoted from experimental to the stable API. These events are now available directly from strands.hooks without the experimental import path.

 from strands.hooks import BeforeNodeCallEvent, AfterNodeCallEvent, HookProvider
 
 class MyMultiagentHook(HookProvider):
     def register_hooks(self, registry):
         registry.add_callback(BeforeNodeCallEvent, self.before_node)
         registry.add_callback(AfterNodeCallEvent, self.after_node)
     
     def before_node(self, event):
         print(f"Starting node: {event.node_id}")
     
     def after_node(self, event):
         print(f"Completed node: {event.node_id}")

Major Bug Fixes

  • MCP Agent Hang Prevention - PR#1396
    Fixed indefinite hangs when MCPClient attempted to schedule tool calls to a background event loop that had already finished, particularly when 4xx/5xx errors caused the loop to exit prematurely.
  • PEP 563 Compatibility with Tool Decorator - PR#1494
    Resolved incompatibility between strands-agents 1.16.0+ and Pydantic 2.12+ when tools use from __future__ import annotations, which caused PydanticUserError due to unresolved string type annotations.
  • Unique Tool Use IDs for Gemini Models - PR#1201
    Fixed Gemini models incorrectly using tool names as tool use IDs instead of generating unique identifiers, ensuring proper tool call tracking and correlation.
  • Bedrock Thinking Mode with Structured Output - PR#1495
    Fixed validation exception when using structured output with thinking mode enabled, by automatically disabling thinking mode when the event loop forces tool_choice during retries.

What's Changed

  • fix(mcp): prevent agent hang by checking session closure state by @Ratish1 in https://github.com/strands-agents/sdk-python/pull/1396
  • ci: update sphinx-rtd-theme requirement from <2.0.0,>=1.0.0 to >=1.0.0,<4.0.0 by @dependabot[bot] in https://github.com/strands-agents/sdk-python/pull/1466
  • ci: update websockets requirement from <16.0.0,>=15.0.0 to >=15.0.0,<17.0.0 by @dependabot[bot] in https://github.com/strands-agents/sdk-python/pull/1451
  • Update ruff configuration to apply pyupgrade to modernize python syntax by @maxrabin in https://github.com/strands-agents/sdk-python/pull/1336
  • fix(agent): extract text from citationsContent in AgentResult.str by @tmokmss in https://github.com/strands-agents/sdk-python/pull/1489
  • Expose input messages to BeforeInvocationEvent hook by @Unshure in https://github.com/strands-agents/sdk-python/pull/1474
  • interrupts - graph - hook based by @pgrayy in https://github.com/strands-agents/sdk-python/pull/1478
  • fix: Swap unit test sleeps with explicit signaling by @zastrowm in https://github.com/strands-agents/sdk-python/pull/1497
  • Fix PEP 563 incompatibility with @tool decorated tools by @zastrowm in https://github.com/strands-agents/sdk-python/pull/1494
  • feat: override service name by OTEL_SERVICE_NAME env by @okamototk in https://github.com/strands-agents/sdk-python/pull/1400
  • fix(bedrock): disable thinking mode when forcing tool_choice by @strands-agent in https://github.com/strands-agents/sdk-python/pull/1495
  • fix(a2a): use a2a artifact update event by @brycewcole in https://github.com/strands-agents/sdk-python/pull/1401
  • Add parallel reading support to S3SessionManager.list_messages() by @CrysisDeu in https://github.com/strands-agents/sdk-python/pull/1186
  • feat(steering): allow steering on AfterModelCallEvents by @dbschmigelski in https://github.com/strands-agents/sdk-python/pull/1429
  • fix: provide unique toolUseId for gemini models by @AirswitchAsa in https://github.com/strands-agents/sdk-python/pull/1201
  • gemini - tool_use_id_to_name - local by @pgrayy in https://github.com/strands-agents/sdk-python/pull/1521
  • fix(litellm): handle missing usage attribute on ModelResponseStream by @dbschmigelski in https://github.com/strands-agents/sdk-python/pull/1520
  • feat(agent): add configurable retry_strategy for model calls by @zastrowm in https://github.com/strands-agents/sdk-python/pull/1424
  • fix(swarm): accumulate execution_time across interrupt/resume cycles by @pgrayy in https://github.com/strands-agents/sdk-python/pull/1502
  • Feat: graduate multiagent hook events from experimental by @JackYPCOnline in https://github.com/strands-agents/sdk-python/pull/1498
  • Nova Sonic 2 support for BidiAgent by @lanazhang in https://github.com/strands-agents/sdk-python/pull/1476
  • fix(tests): reduce flakiness in guardrail redact output test by @dbschmigelski in https://github.com/strands-agents/sdk-python/pull/1505

New Contributors

  • @maxrabin made their first contribution in https://github.com/strands-agents/sdk-python/pull/1336
  • @tmokmss made their first contribution in https://github.com/strands-agents/sdk-python/pull/1489
  • @okamototk made their first contribution in https://github.com/strands-agents/sdk-python/pull/1400
  • @strands-agent made their first contribution in https://github.com/strands-agents/sdk-python/pull/1495
  • @brycewcole made their first contribution in https://github.com/strands-agents/sdk-python/pull/1401
  • @CrysisDeu made their first contribution in https://github.com/strands-agents/sdk-python/pull/1186
  • @AirswitchAsa made their first contribution in https://github.com/strands-agents/sdk-python/pull/1201
  • @lanazhang made their first contribution in https://github.com/strands-agents/sdk-python/pull/1476

Full Changelog: https://github.com/strands-agents/sdk-python/compare/v1.22.0...v1.23.0

Weekly OSS security release digest.

The CVE patches and breaking changes that affected production tools this week. One email, every Sunday.

No spam, unsubscribe anytime.

Share this release

Track harness-sdk

Get notified when new releases ship.

Sign up free

About harness-sdk

A model-driven approach to building AI agents in just a few lines of code.

All releases →

Related context

Beta — feedback welcome: [email protected]