The Strands Agents (Python) adapter for Welt's wire contract
Project description
welt-io-strands
The Strands Agents (Python) adapter for Welt's wire contract — one of Welt's agent-side adapters.
Install
uv add welt-io-strands
Usage
See examples/agent — the smallest complete agent built on this package (text streaming, image generation, file input, and a human-approval tool), which doubles as the example for Welt's Quick Start. The sections below explain the adapters it wires in.
API
The wire between Welt and the agent is JSON, specified by Welt's wire contract — plain Strands values do not fit it in either direction. Two functions adapt the inbound payload, three the outbound stream.
Inbound
decode_messages(messages)
Returns a copy of Welt's Converse-shaped messages with the base64-encoded file bytes restored to the raw bytes Strands expects; the input is left untouched. Its in-place predecessor, decode_file_blocks(messages), is deprecated.
decode_interrupt_responses(responses)
Turns Welt's resume payload — a mapping of interrupt id to the answer a human chose — into the interruptResponse items that Agent.stream_async resumes from.
Outbound
renderable_events(events)
Reduces raw stream_async events — not JSON-serializable as-is — to the events Welt renders:
| Strands emits | On the wire | In the Slack thread |
|---|---|---|
| Text deltas | data |
The streamed reply |
| Tool invocations and results | current_tool_use / tool_result |
"Using tool" indicators (tool output stays off the wire) |
| Image / document / video blocks a tool or the model produces | file |
An uploaded file (size limits) |
| Pending interrupts | interrupt |
Buttons and/or a text field |
A run that stops for human input ends its stream with one interrupt event per pending interrupt; agents that do not use interrupts see no change.
file_event(name, data)
Builds the same file event from a filename and raw bytes, for attaching arbitrary files of your own:
yield file_event("report.csv", csv_bytes)
Tool-generated files need no code at all — for example, strands-tools' generate_image returns the image as a tool-result block, which streams into the thread by itself. The example agent includes it.
interrupt_reason(message, options=..., input=...)
Builds the structured reason Welt renders as a message with the specified widgets — choice buttons (options), a free-text field (input), or both. The specs are the wire's own shapes; omitted fields keep Welt's defaults, and a typo becomes an immediate ValueError instead of a silent fallback to Welt's default rendering:
answer = tool_context.interrupt(
"deploy-approval",
reason=interrupt_reason(
"Deploy to prod?",
[
{"value": "y", "label": "Deploy", "style": "primary"},
{"value": "n", "label": "Cancel"},
],
input={"label": "Or tell me what to do instead"},
),
)
Working with interrupts
Welt's Interrupts doc covers the Slack side: how each reason renders, who can answer, multiple questions, and expiry. On the Strands side:
- Prefix your interrupt names (
myapp-deploy-approval). Hook-raised interrupts must be unique across the whole event, tool-raised ones within their tool — a prefix keeps both as the agent grows. - Strands' ready-made
HumanInTheLoopintervention works over Welt as-is. Its string reasons render with Welt's default Approve / Deny buttons, whosey/nvalues its default evaluator understands. Do not passask: stdio prompts and callback evaluators have no terminal on AgentCore Runtime. - Route stdio consent prompts through interrupts instead. For strands-tools packages that gate themselves behind a stdio prompt, set
BYPASS_TOOL_CONSENT=trueand letHumanInTheLoopdo the gating over Slack. The strands-toolshandoff_to_usertool is likewise stdio-bound; a small interrupt-raising tool of your own is the replacement.
Supported Versions
Welt releases first; welt-io-strands follows, mirroring the minor version. While both are 0.x, a welt-io-strands 0.Y release supports Welt v0.Y — other combinations may work, but come with no guarantee.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file welt_io_strands-0.3.3.tar.gz.
File metadata
- Download URL: welt_io_strands-0.3.3.tar.gz
- Upload date:
- Size: 16.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.29 {"installer":{"name":"uv","version":"0.11.29","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
513a533312d9f0637f9d7e81a4dd19d232983b986cff3733bd9ffb23eccc27e5
|
|
| MD5 |
9b2b5840de114ef2fdddd51777ed1c44
|
|
| BLAKE2b-256 |
680f37b66908ba6eea232862fe1a0d466a4eb173de78963c7be00e8a9908d6e2
|
File details
Details for the file welt_io_strands-0.3.3-py3-none-any.whl.
File metadata
- Download URL: welt_io_strands-0.3.3-py3-none-any.whl
- Upload date:
- Size: 9.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.29 {"installer":{"name":"uv","version":"0.11.29","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
11afbac805f83dd7f4b9a0450e52bb414ea7e3e0a8e7c6e494f8de8877dec3fa
|
|
| MD5 |
c2a5fad7c8b142163f75ff62085ade2a
|
|
| BLAKE2b-256 |
4713e7226beea725d113552c8fdd19f92a1b888a4889e613753fd5ba5dc9885f
|