Agent-ready provider API wrappers with typed schemas, OAuth scope mappings, and LLM function-calling definitions.
Provider SDKs are designed for human developers — they expose hundreds or thousands of operations per provider. apron-tools adds what agents need:
- LLM function-calling schemas — structured tool definitions generated from Pydantic models.
- Curation — a selected subset of operations useful for agents, not the entire API surface.
- Tool-to-scope mappings — which OAuth scopes each tool requires.
- Provider quirk handling — surfaced and handled, not buried in SDK internals.
apron-tools defines tools, not transport. The same definitions can be served as MCP, OpenAPI, GraphQL, or plain Python callables. Tool definitions are more durable than wire protocols.
# Core only (tool definitions and schemas, no provider SDK dependencies).
# via uv
uv add apron-tools
# via pip
pip install apron-tools
# With specific provider extras (installs provider SDK dependencies).
# via uv
uv add apron-tools --extra slack --extra google
# via pip
pip install apron-tools[slack,google]
# All providers.
# via uv
uv add apron-tools --extra all
# via pip
pip install apron-tools[all]from apron_tools import discover_tools, get_tools_for_provider
# Discover tools across all installed providers.
# Only providers whose dependencies are installed will be found.
tools = discover_tools()
# Tools for a specific provider.
typeform_tools = get_tools_for_provider("typeform")
for td in typeform_tools:
print(f"{td.name}: {td.description}")
print(f" scopes: {td.scopes}")
print(f" docs: {td.api_docs_url}")from apron_tools.providers.typeform.tools import list_forms
from apron_tools.providers.typeform.types import ListFormsParams
result = await list_forms(ListFormsParams(page_size=10), token="your-typeform-token")
# Typed attribute access.
for form in result.items:
print(f"{form.title} ({form.id})")
# LLM-readable string.
print(str(result))
# Dict or JSON.
result.model_dump()
result.model_dump_json()Every tool function decorated with @tool has a _tool_definition attribute containing its metadata:
from apron_tools.providers.typeform.tools import list_forms
td = list_forms._tool_definition
td.name # "list_forms"
td.provider # "typeform"
td.scopes # ["forms:read"]
td.input_schema # JSON Schema from the Pydantic input model
td.output_schema # JSON Schema from the Pydantic output model
td.api_docs_url # "https://www.typeform.com/developers/create/reference/retrieve-forms/"Each provider is a directory under src/apron_tools/providers/:
src/apron_tools/providers/yourprovider/
├── __init__.py # Export tool functions
├── types.py # Pydantic input/output models
├── tools.py # Async tool functions with @tool decorator
└── scopes.py # OAuth scope enum and mappings
See src/apron_tools/providers/typeform/ for the reference implementation.
- Create provider directory with
types.py,tools.py,scopes.py,__init__.py. - Add API docs URLs in
@tooldecorator and provider__init__.pydocstring. - Capture real API response snapshots in
tests/providers/yourprovider/testdata/. - Write tests — model validation, tool function tests (mocked HTTP), contract snapshots.
- Optionally add integration tests in
test_integration.py.
Requires uv.
make setup # Install uv, create venv, sync deps, install pre-commit hooks
make test # Run unit tests (integration tests skipped by default)
make lint # Run pre-commit hooks (ruff, ty, detect-secrets)
make test-integration # Run integration tests (requires provider tokens)Or using uv directly:
uv sync --group dev # Sync all dev dependencies
uv run pytest tests # Run tests
uv run pre-commit run --all-files # Run lintersIntegration tests call real provider APIs and are skipped by default. To run them:
APRON_TOOLS_INTEGRATION_TESTS=1 TYPEFORM_TOKEN=xxx make test-integrationEach provider has its own token env var. Only providers with credentials set will run; the rest skip cleanly:
# Run just Slack integration tests.
APRON_TOOLS_INTEGRATION_TESTS=1 SLACK_TOKEN=xoxb-... make test-integration
# Run Google + Notion integration tests.
APRON_TOOLS_INTEGRATION_TESTS=1 GOOGLE_TOKEN=... NOTION_TOKEN=... make test-integration