Skip to main content

agentpack

Zero-Config Python SDK for Agentpack Tools

Drop a .py file in your repo and get a production-ready, containerized, gRPC-enabled tool—instantly. No servers. No Docker. No infrastructure code.

Installation

pip install agentpack
# or
poetry add agentpack
# or
uv pip install agentpack

Quick Start

1. Write ONLY Business Logic

# tools/greet.py
from pydantic import BaseModel
from agentpack import tool, ExecutionContext

class GreetInput(BaseModel):
    name: str

class GreetOutput(BaseModel):
    greeting: str

@tool(
    name="greet",
    description="Greet a person by name",
    input_schema=GreetInput,
    output_schema=GreetOutput,
)
async def greet(input: GreetInput, ctx: ExecutionContext) -> GreetOutput:
    ctx.logger.info("Greeting user", name=input.name)
    return GreetOutput(greeting=f"Hello, {input.name}!")

2. That's It!

No step 2. Agentpack Builder automatically:

  • Discovers tools in tools/ directory
  • Generates .agentpack-manifest.json
  • Creates optimized Dockerfile
  • Builds OCI image with gRPC runtime
  • Deploys to container backend

Agentpack Runtime automatically:

  • Loads tools from manifest
  • Starts gRPC server (port 50051)
  • Handles execution via Rust core
  • Provides full observability

Zero-Config Architecture

┌─────────────────────────────────────────────────┐
│  YOU: Write tools/calculator.py                 │
│  ↓                                              │
│  BUILDER: Scan → Manifest → Dockerfile → Image │
│  ↓                                              │
│  RUNTIME: Load → gRPC Server → Execute         │
│  ↓                                              │
│  RUST CORE: Orchestrate with Tower middleware  │
└─────────────────────────────────────────────────┘

You own: Business logic (100% focus) Agentpack owns: Servers, containers, orchestration, observability

Features

Built-In, Zero Setup:

  • Type-Safe: Full type inference with Pydantic
  • Validated: Automatic input/output validation
  • Observable: OpenTelemetry tracing (no config)
  • Secure: Secret management via dashboard
  • Resilient: HTTP client with automatic retries
  • Structured Logging: Request-scoped context
  • gRPC: High-performance protocol (auto-configured)
  • Containerized: OCI images with base runtime
  • Sandboxed: gVisor/Firecracker isolation

Execution Context

Every tool handler receives ctx with production-ready utilities:

Secrets

# Get optional secret
api_key = await ctx.secrets.get("API_KEY")

# Get required secret (raises if missing)
api_key = await ctx.secrets.require("API_KEY")

# Secrets configured via Agentpack Dashboard:
# - vault://kv/my-secret
# - aws-sm://secret-name
# - gcp-sm://projects/*/secrets/*

HTTP Client

# GET with automatic retries
response = await ctx.http.get(
    "https://api.example.com/data",
    params={"limit": 10},
    headers={"Authorization": f"Bearer {token}"},
)

# POST, PUT, DELETE also available
response = await ctx.http.post(
    "https://api.example.com/data",
    json={"name": "value"},
)

Logger

ctx.logger.info("Processing request", user_id="123")
ctx.logger.error("Something went wrong", error=str(err))

# Logs automatically include:
# - Request ID
# - Trace ID
# - Tool name
# - Timestamp

Tracer (OpenTelemetry)

span = ctx.trace.start_span("external-api-call")
try:
    # ... do work ...
    span.set_attribute("items.count", len(items))
finally:
    span.end()

# Traces sent to OpenTelemetry Collector automatically

Examples

See examples/ directory:

Simple Tool (examples/calculator.py)

from enum import Enum
from pydantic import BaseModel
from agentpack import tool, ExecutionContext

class Operation(str, Enum):
    ADD = "add"
    SUBTRACT = "subtract"
    MULTIPLY = "multiply"
    DIVIDE = "divide"

class CalculatorInput(BaseModel):
    operation: Operation
    a: float
    b: float

class CalculatorOutput(BaseModel):
    result: float
    operation: str

@tool(
    name="calculator",
    description="Perform basic arithmetic operations",
    input_schema=CalculatorInput,
    output_schema=CalculatorOutput,
)
async def calculator(input: CalculatorInput, ctx: ExecutionContext) -> CalculatorOutput:
    # Pure business logic
    if input.operation == Operation.ADD:
        result = input.a + input.b
    elif input.operation == Operation.SUBTRACT:
        result = input.a - input.b
    elif input.operation == Operation.MULTIPLY:
        result = input.a * input.b
    elif input.operation == Operation.DIVIDE:
        if input.b == 0:
            raise ValueError("Division by zero")
        result = input.a / input.b

    return CalculatorOutput(
        result=result,
        operation=f"{input.a} {input.operation.value} {input.b}"
    )

External API Tool (examples/weather.py)

Demonstrates:

  • Secret management (ctx.secrets.require())
  • HTTP client with retries (ctx.http.get())
  • Structured logging
  • Input validation with Pydantic

API Reference

@tool Decorator

Create a tool definition.

from pydantic import BaseModel
from agentpack import tool, ExecutionContext

class MyInput(BaseModel):
    value: int

class MyOutput(BaseModel):
    result: int

@tool(
    name="my_tool",                    # Unique tool identifier
    description="My tool description", # Human-readable description
    input_schema=MyInput,              # Pydantic input model
    output_schema=MyOutput,            # Pydantic output model
)
async def my_tool(input: MyInput, ctx: ExecutionContext) -> MyOutput:
    return MyOutput(result=input.value * 2)

Parameters:

  • name (str): Unique tool name
  • description (str): Human-readable description
  • input_schema (BaseModel): Pydantic input validation model
  • output_schema (BaseModel): Pydantic output validation model

Returns: Tool instance (internal use by runtime)

Error Handling

from agentpack import (
    ToolError,
    ValidationError,
    SecretNotFoundError,
    HttpError,
)

async def my_handler(input: MyInput, ctx: ExecutionContext) -> MyOutput:
    # Validation errors raised automatically by Pydantic

    # Secret not found
    key = await ctx.secrets.require("API_KEY")  # raises SecretNotFoundError

    # HTTP errors from external APIs
    response = await ctx.http.get("...")  # raises HttpError on failure

    # Custom errors
    if not input.valid:
        raise ToolError("Invalid input", "INVALID_INPUT")

Multi-File Tools

Tools can have dependencies:

tools/
├── calculator/
│   ├── __init__.py      # Entry point (exports tool)
│   ├── operations.py    # Helper functions
│   └── types.py         # Shared types
└── weather.py           # Single-file tool

Builder discovers both patterns automatically:

  • Single-file: tools/weather.py
  • Multi-file: tools/calculator/__init__.py

Testing

import pytest
from pydantic import BaseModel
from agentpack import tool, ExecutionContext

class TestInput(BaseModel):
    value: int

class TestOutput(BaseModel):
    result: int

@tool(
    name="test_tool",
    description="Test tool",
    input_schema=TestInput,
    output_schema=TestOutput,
)
async def test_tool(input: TestInput, ctx: ExecutionContext) -> TestOutput:
    return TestOutput(result=input.value * 2)

@pytest.mark.asyncio
async def test_my_tool():
    # Create mock context
    from agentpack.context import create_execution_context
    from agentpack.types import RequestMetadata

    metadata = RequestMetadata(request_id="123")
    ctx = create_execution_context(metadata)

    # Execute tool
    result = await test_tool.execute({"value": 5}, ctx)
    assert result.result == 10

Deployment

Nothing to do! Builder + Runtime handle everything:

  1. Build: agentpack build (or automatic via GitHub App)
  2. Deploy: Automatic to Agentpack infrastructure
  3. Scale: Automatic based on load
  4. Monitor: Traces/logs in dashboard

Configuration

Optional agentpack.yaml for advanced settings:

version: 0.1
project: my-tools

agents:
  - name: default
    model: { provider: anthropic, name: claude-3-5-sonnet }
    tools: ["*"]  # All tools in tools/

resources:
  - name: stripe_secret
    type: secret
    source: vault://kv/stripe

policies:
  outbound_network:
    allow: ["*.stripe.com", "*.openai.com"]

Thin SDK Philosophy

This SDK is intentionally minimal:

  • @tool decorator for definitions
  • ExecutionContext types
  • ✅ Error classes
  • ❌ NO server creation
  • ❌ NO Docker setup
  • ❌ NO deployment code

All orchestration lives in Rust core for:

  • Consistent cross-language behavior
  • Performance (Tower middleware)
  • Security (policy enforcement)
  • Observability (OpenTelemetry)

Type Checking

The SDK is fully typed and works with mypy:

mypy tools/ --strict

Troubleshooting

"Tool not found" error

  • Ensure tool is in tools/ directory
  • Check file exports tool with @tool decorator
  • Verify .agentpack-manifest.json was generated

Validation errors

  • Check Pydantic model matches input
  • Use Optional[T] or = Field(default=...) for optional fields
  • Test with mock data

Secret not found

  • Configure secrets in Agentpack Dashboard
  • Use correct secret key name
  • Check environment variables in development

Related Packages

  • agentpack-runtime-python - Internal gRPC runtime (private)
  • @agentpack/sdk - TypeScript SDK (same zero-config approach)

License

MIT OR Apache-2.0

Release files for agentpack 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for agentpack 0.1.0
File Size Uploaded
agentpack-0.1.0.tar.gz 25.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for agentpack 0.1.0
File Interpreter ABI Platform
agentpack-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 37.8 kB

Release files / agentpack-0.1.0.tar.gz

Download URL agentpack-0.1.0.tar.gz
Size 25.2 kB
Tags Source
SHA-256 checksum
How to use checksums
d398dee12a6ca0b54ff89bfdb4f3e80df590c9d776a73a6f93d7851211667503
BLAKE2b-256 checksum
How to use checksums
9d2b3a18e00408ccf04f4649f3ed926decb10f06706c057ec47970373725e488
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.0

Release files / agentpack-0.1.0-py3-none-any.whl

Download URL agentpack-0.1.0-py3-none-any.whl
Size 12.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a69f8b08cf6c959d30d0cb8cc0adb802fc222a85cb125f8eacac450ce3634e40
BLAKE2b-256 checksum
How to use checksums
ce3f1a74ff566f882fb24eff8652bcfca02a5e6517d433dca4479ce410ffc320
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.0

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page