Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
2a26ffa
fix(litellm): map LiteLLM context-window errors to ContextWindowOverf…
Ratish1 Oct 7, 2025
171779a
feat: Refactor and update tool loading to support modules (#989)
Unshure Oct 8, 2025
1790b2d
Adding Development Tenets to CONTRIBUTING.md (#1009)
Unshure Oct 8, 2025
92da544
Revert "feat: implement concurrent message reading for session manage…
pgrayy Oct 9, 2025
2f04758
feat(models): use tool for litellm structured_output when supports_re…
dbschmigelski Oct 9, 2025
aada326
feat(mcp): Add EmbeddedResource support to mcp (#726)
KyMidd Oct 9, 2025
9632ed5
conversation manager - summarization - noop tool (#1003)
pgrayy Oct 9, 2025
419de19
Fix additional_args passing in SageMakerAIModel (#983)
athewsey Oct 10, 2025
7fbc9dc
feat: replace kwargs with invocation_state in agent APIs (#966)
JackYPCOnline Oct 10, 2025
355b3bb
feat(telemetry): updated semantic conventions, added timeToFirstByteM…
poshinchen Oct 14, 2025
c3e5f6b
chore(telemetry): added gen_ai.tool.description and gen_ai.tool.json_…
poshinchen Oct 14, 2025
6cf4f7e
fix(tool/decorator): validate ToolContext parameter name and raise cl…
Ratish1 Oct 14, 2025
f7931c5
integ tests - fix flaky structured output test (#1030)
pgrayy Oct 14, 2025
dbf6200
hooks - before tool call event - interrupt (#987)
pgrayy Oct 15, 2025
61e41da
multiagents - temporarily raise exception when interrupted (#1038)
pgrayy Oct 16, 2025
7cd10b9
feat: Support adding exception notes for Python 3.10 (#1034)
zastrowm Oct 16, 2025
26862e4
interrupts - decorated tools (#1041)
pgrayy Oct 17, 2025
3a7af77
models - litellm - start and stop reasoning (#947)
pgrayy Oct 21, 2025
b69478b
feat: add experimental AgentConfig with comprehensive tool management…
mr-lee Oct 21, 2025
78c59b9
fix(telemetry): make strands agent invoke_agent span as INTERNAL span…
poshinchen Oct 21, 2025
8a89d91
feat: add multiagent hooks, add serialize & deserialize function to m…
JackYPCOnline Oct 22, 2025
648af22
feat: Add Structured Output as part of the agent loop (#943)
afarntrog Oct 22, 2025
de802fb
integ tests - interrupts - remove asyncio marker (#1045)
pgrayy Oct 23, 2025
d4ef8bf
interrupt - docstring - fix formatting (#1074)
pgrayy Oct 24, 2025
1544384
ci: add pr size labeler (#1082)
dbschmigelski Oct 24, 2025
999e654
fix: Don't bail out if there are no tool_uses (#1087)
zastrowm Oct 24, 2025
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
58 changes: 58 additions & 0 deletions .github/workflows/pr-size-labeler.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
name: PR Size Labeler

on:
pull_request_target:
branches: main

jobs:
label-size:
runs-on: ubuntu-latest
permissions:
pull-requests: write
issues: write
steps:
- name: Calculate PR size and apply label
uses: actions/github-script@v8
with:
script: |
const pr = context.payload.pull_request;
const totalChanges = pr.additions + pr.deletions;

// Remove existing size labels
const labels = await github.rest.issues.listLabelsOnIssue({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.pull_request.number
});

for (const label of labels.data) {
if (label.name.startsWith('size/')) {
await github.rest.issues.removeLabel({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.pull_request.number,
name: label.name
});
}
}

// Determine and apply new size label
let sizeLabel;
if (totalChanges <= 20) sizeLabel = 'size/xs';
else if (totalChanges <= 100) sizeLabel = 'size/s';
else if (totalChanges <= 500) sizeLabel = 'size/m';
else if (totalChanges <= 1000) sizeLabel = 'size/l';
else {
sizeLabel = 'size/xl';
}

await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.pull_request.number,
labels: [sizeLabel]
});

if (sizeLabel === 'size/xl') {
core.setFailed(`PR is too large (${totalChanges} lines). Please split into smaller PRs.`);
}
5 changes: 5 additions & 0 deletions .github/workflows/test-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ jobs:
id: tests
run: hatch test tests --cover
continue-on-error: false

- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
lint:
name: Lint
runs-on: ubuntu-latest
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ __pycache__*
.vscode
dist
repl_state
.kiro
.kiro
uv.lock
12 changes: 12 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,18 @@ Before starting work on any issue:
3. Wait for maintainer confirmation before beginning significant work


## Development Tenets
Our team follows these core principles when designing and implementing features. These tenets help us make consistent decisions, resolve trade-offs, and maintain the quality and coherence of the SDK. When contributing, please consider how your changes align with these principles:

1. **Simple at any scale:** We believe that simple things should be simple. The same clean abstractions that power a weekend prototype should scale effortlessly to production workloads. We reject the notion that enterprise-grade means enterprise-complicated - Strands remains approachable whether it's your first agent or your millionth.
2. **Extensible by design:** We allow for as much configuration as possible, from hooks to model providers, session managers, tools, etc. We meet customers where they are with flexible extension points that are simple to integrate with.
3. **Composability:** Primitives are building blocks with each other. Each feature of Strands is developed with all other features in mind, they are consistent and complement one another.
4. **The obvious path is the happy path:** Through intuitive naming, helpful error messages, and thoughtful API design, we guide developers toward correct patterns and away from common pitfalls.
5. **We are accessible to humans and agents:** Strands is designed for both humans and AI to understand equally well. We don’t take shortcuts on curated DX for humans and we go the extra mile to make sure coding assistants can help you use those interfaces the right way.
6. **Embrace common standards:** We respect what came before, and do not want to reinvent something that is already widely adopted or done better.

When proposing solutions or reviewing code, we reference these principles to guide our decisions. If two approaches seem equally valid, we choose the one that best aligns with our tenets.

## Development Environment

This project uses [hatchling](https://hatch.pypa.io/latest/build/#hatchling) as the build backend and [hatch](https://hatch.pypa.io/latest/) for development workflow management.
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ dependencies = [
"boto3>=1.26.0,<2.0.0",
"botocore>=1.29.0,<2.0.0",
"docstring_parser>=0.15,<1.0",
"jsonschema>=4.0.0,<5.0.0",
"mcp>=1.11.0,<2.0.0",
"pydantic>=2.4.0,<3.0.0",
"typing-extensions>=4.13.2,<5.0.0",
Expand Down
10 changes: 9 additions & 1 deletion src/strands/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,12 @@
from .tools.decorator import tool
from .types.tools import ToolContext

__all__ = ["Agent", "agent", "models", "tool", "types", "telemetry", "ToolContext"]
__all__ = [
"Agent",
"agent",
"models",
"tool",
"ToolContext",
"types",
"telemetry",
]
21 changes: 21 additions & 0 deletions src/strands/_exception_notes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
"""Exception note utilities for Python 3.10+ compatibility."""

# add_note was added in 3.11 - we hoist to a constant to facilitate testing
supports_add_note = hasattr(Exception, "add_note")


def add_exception_note(exception: Exception, note: str) -> None:
"""Add a note to an exception, compatible with Python 3.10+.

Uses add_note() if it's available (Python 3.11+) or modifies the exception message if it is not.
"""
if supports_add_note:
# we ignore the mypy error because the version-check for add_note is extracted into a constant up above and
# mypy doesn't detect that
exception.add_note(note) # type: ignore
else:
# For Python 3.10, append note to the exception message
if hasattr(exception, "args") and exception.args:
exception.args = (f"{exception.args[0]}\n{note}",) + exception.args[1:]
else:
exception.args = (note,)
Loading
Loading