Skip to main content

Standalone SDK for developing Solace Agent Mesh Python tools

Project description

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.

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

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sam_tool_sdk-0.1.1.tar.gz (52.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

sam_tool_sdk-0.1.1-py3-none-any.whl (51.3 kB view details)

Uploaded Python 3

File details

Details for the file sam_tool_sdk-0.1.1.tar.gz.

File metadata

  • Download URL: sam_tool_sdk-0.1.1.tar.gz
  • Upload date:
  • Size: 52.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for sam_tool_sdk-0.1.1.tar.gz
Algorithm Hash digest
SHA256 a0fe21aeb919590ccea144c44a31bf4de5178e7e94141584000bd0f5cb9969be
MD5 f2bd97782b4cbb46b6fc7acdebe37e76
BLAKE2b-256 1ec4eb6b3851c1655013dc9930bc7e48c3c3913262f46c3d974b2f388b9b22fc

See more details on using hashes here.

Provenance

The following attestation bundles were made for sam_tool_sdk-0.1.1.tar.gz:

Publisher: python-sdk-release.yml on SolaceDev/solace-agent-mesh-go

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file sam_tool_sdk-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: sam_tool_sdk-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 51.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for sam_tool_sdk-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 ee965f6da904971942d074c2d2df88acc39ed53da316d902a4d242dd93598988
MD5 e68366a5b3e1abd1678fa1d5e4479750
BLAKE2b-256 7006cdce9a2c7f6afb0af70a9c90a2caf52ff5d396854b476228ed4089eac6c8

See more details on using hashes here.

Provenance

The following attestation bundles were made for sam_tool_sdk-0.1.1-py3-none-any.whl:

Publisher: python-sdk-release.yml on SolaceDev/solace-agent-mesh-go

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page