SAM Tool SDK
Python SDK for building tools that run in Solace Agent Mesh (SAM).
What it does
Write a Python function (or class) and expose it as a SAM tool. Type
annotations become the tool's parameter schema, the docstring supplies the
descriptions the LLM sees, and you return structured results and artifacts.
The SAM runtime discovers the tool and invokes it per call. The only
dependency is pydantic.
Installation
pip install sam-tool-sdk
Quick Start
Function-based tool with tool_cli
The canonical pattern: author a function, wrap it with tool_cli, and expose
the resulting callable as a console script via pyproject.toml.
# greet_tool.py
from sam_tool_sdk import tool_cli, ToolResult, SandboxToolContextFacade
async def greet(name: str, excited: bool = False, ctx: SandboxToolContextFacade = None) -> ToolResult:
"""Greet someone by name.
Args:
name: who to greet
excited: add an exclamation mark
"""
if ctx is not None:
ctx.send_status(f"Greeting {name}...")
suffix = "!" if excited else "."
return ToolResult.ok(message=f"Hello, {name}{suffix}", data={"greeted": name})
cli = tool_cli(greet)
# pyproject.toml
[project]
name = "sam-tool-greet"
version = "0.1.0"
dependencies = ["sam-tool-sdk>=0.1,<0.2"]
[project.scripts]
greet = "greet_tool:cli"
Parameter type annotations (str, bool, int, Artifact,
SandboxToolContextFacade, …) and the docstring's Args: block produce the
JSON Schema the LLM sees. The SandboxToolContextFacade-annotated parameter is
injected at runtime; everything else becomes a tool argument. Besides
send_status, artifacts and config, the facade exposes the caller's identity:
ctx.user_id, ctx.session_id, ctx.app_name, ctx.task_id, and
ctx.user_profile (the gateway-forwarded profile as a dict, empty when none).
The profile is unsigned, so use it to scope lookups and attribute audit
records, not as the sole basis for an authorization decision.
Class-based tool (DynamicTool)
For more control over the tool's schema and behavior:
from sam_tool_sdk import DynamicTool, ToolResult
class WordCounter(DynamicTool):
@property
def tool_name(self):
return "count_words"
@property
def tool_description(self):
return "Counts the number of words in the given text."
@property
def parameters_schema(self):
return {
"type": "object",
"properties": {
"text": {"type": "string", "description": "The text to count words in"},
},
"required": ["text"],
}
async def _run_async_impl(self, args, tool_context=None, credential=None):
count = len(args["text"].split())
return ToolResult.ok(f"Found {count} words", data={"count": count}).model_dump()
Provider-based tools (DynamicToolProvider)
When you want to define multiple related tools from a single class:
from sam_tool_sdk import DynamicToolProvider
class MathTools(DynamicToolProvider):
@MathTools.register_tool
async def add(self, a: float, b: float) -> dict:
"""Add two numbers."""
return {"text": str(a + b)}
@MathTools.register_tool
async def multiply(self, a: float, b: float) -> dict:
"""Multiply two numbers."""
return {"text": str(a * b)}
def create_tools(self, tool_config=None):
return [] # All tools defined via @register_tool
Declaring operator config (config_schema)
Tools that need operator-supplied configuration (API keys, endpoints, default
channels, …) declare it with @with_config_schema so the platform can render a
config form, validate per-agent overrides, and enforce required fields at
deploy time.
from sam_tool_sdk import ConfigSchemaField, with_config_schema
@with_config_schema([
ConfigSchemaField(
key="slack_bot_token",
type="string",
description="Slack Bot OAuth token (xoxb-...).",
required=True,
secret=True,
),
ConfigSchemaField(key="default_channel", type="string"),
ConfigSchemaField(key="api_url", type="string"),
])
async def post_message(tool_config, channel: str, text: str):
token = tool_config["slack_bot_token"]
...
Values are resolved at deploy time with precedence: agent override > toolset
default > schema default > 422 if a required field is unset. Fields marked
secret=True are redacted on API responses and rendered with a password input
in the UI.
For DynamicTool subclasses, override the config_schema property to return a
list of ConfigSchemaField(...).to_dict() entries.
Working with artifacts
Tools can receive and produce artifacts using type annotations:
from sam_tool_sdk import Artifact, ToolResult, DataObject, DataDisposition
async def summarize_file(doc: Artifact) -> ToolResult:
"""Summarize the contents of an uploaded document."""
text = doc.as_text()
summary = text[:200] + "..." # placeholder for real summarization
return ToolResult.ok(
message=f"Summarized {doc.filename}",
data={"summary": summary},
data_objects=[
DataObject(
name="summary.txt",
content=summary,
mime_type="text/plain",
disposition=DataDisposition.ARTIFACT,
description="Document summary",
)
],
)
Per-tool sandbox options
Decorate a tool_cli function (or override the matching DynamicTool
properties) to declare timeouts and volume requirements honored at execution
time:
from sam_tool_sdk import tool_cli, tool_timeout, with_volume_params, VolumeParam, ToolResult
@tool_timeout(seconds=120)
@with_volume_params([
VolumeParam(name="workspace", mount_path="/workspace", mode="readwrite"),
])
async def transform(input_path: str, ctx=None) -> ToolResult:
"""Long-running transformation that needs scratch space."""
...
cli = tool_cli(transform)
tool_timeout overrides the per-invocation timeout; with_volume_params
declares mount points provisioned before the tool runs (paths surface via
ctx.volume_mounts / ctx.get_volume_mount_path("/workspace"), keyed by mount
path).
Packaging
A SAM tool ships as an
AWS-Lambda-Layer-style
directory: a python/bin/<console-script> entry point plus all dependencies
pre-extracted under python/. Build that layout with a single
pip install --target invocation:
pip install --target dist/python \
--platform manylinux2014_x86_64 \
--python-version 3.13 \
--only-binary=:all: \
.
The directory then contains dist/python/bin/<your-script>,
dist/python/sam_tool_sdk/, dist/python/pydantic/, and your own package.
Pair it with a manifest.yaml declaring executable: python/bin/<your-script>.
License
Apache-2.0
Metadata
Release files for sam-tool-sdk 0.1.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| sam_tool_sdk-0.1.3.tar.gz | 64.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| sam_tool_sdk-0.1.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 118.9 kB
Release files / sam_tool_sdk-0.1.3.tar.gz
| Download URL | sam_tool_sdk-0.1.3.tar.gz |
|---|---|
| Size | 64.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5a63dd2c8ae857e785ceda188eff1f95b37a9299f2f4050f5da4b7773d1f22fb
|
|
BLAKE2b-256 checksum How to use checksums |
99262da6f05c2cb8d43403468d99e444fbe57c21976e4b7ac2c9a378bd3122a5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 10, 2026.
Transparency logRelease files / sam_tool_sdk-0.1.3-py3-none-any.whl
| Download URL | sam_tool_sdk-0.1.3-py3-none-any.whl |
|---|---|
| Size | 54.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
0b337cb4ff78402dda868e09fcc96632497958cae0bf9178e45d397910f4de3c
|
|
BLAKE2b-256 checksum How to use checksums |
37b8339d93ab25ae3b8a9a0e541c6e0e8de233a03ade781bb099dee08b310465
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 10, 2026.
Transparency log