Getting started¶
This path proves a complete agent/tool run locally, then replaces the fake model with a
real provider. It needs Python 3.12 or newer and either standard pip or
uv. The repository uses uv and CPython 3.14 for its own
development while testing the full declared 3.12–3.14 range.
1. Install¶
PyPI trusted publishing is not enabled yet. Install the exact tagged v0.53.1 wheel from the public GitHub Release rather than asking an index for a project that is not there. The distribution name uses a hyphen; the Python import uses an underscore.
With pip:
python -m venv .venv
.venv/bin/python -m pip install "tesserix-adk @ https://github.com/tesserix/agent-development-kit/releases/download/v0.53.1/tesserix_adk-0.53.1-py3-none-any.whl"
.venv/bin/python -c "import tesserix_adk; print(tesserix_adk.__version__)"
With uv, from an application project:
uv add "tesserix-adk @ https://github.com/tesserix/agent-development-kit/releases/download/v0.53.1/tesserix_adk-0.53.1-py3-none-any.whl"
uv run python -c "import tesserix_adk; print(tesserix_adk.__version__)"
Optional integrations use the same extras with either installer. For example,
tesserix-adk[a2a,google-adk,mcp] installs the official A2A, Google Agent Development
Kit bridge, and MCP dependencies. The release workflow clean-installs every individual
extra and all with pip before publishing succeeds.
Use the public source checkout only when contributing to this repository:
git clone https://github.com/tesserix/agent-development-kit.git
cd agent-development-kit
uv sync --frozen
2. Prove the offline path¶
The getting-started example scripts the model's tool call and structured final answer. It performs the same declaration, registration, validation, budget enforcement, dispatch, and streamed run loop as a live model, but it opens no connection and reads no credential.
"""Run a typed, tool-using agent with a readable trace and no network."""
from __future__ import annotations
import asyncio
from pydantic import BaseModel
from tesserix_adk import Agent, AgentRunner, ToolRegistry, tool
from tesserix_adk.core import BudgetLimits
from tesserix_adk.testing import FakeModelProvider, ScriptedTurn
class PackingTip(BaseModel):
"""A packing suggestion validated before it reaches the application."""
suggestion: str
@tool(idempotency="read_only")
def current_weather(city: str) -> str:
"""Return the current weather for a city."""
return f"{city} is 21°C and clear"
async def main() -> None:
"""Run the same declaration and registry used with a real provider."""
agent: Agent[PackingTip] = Agent(
name="weather-agent",
instructions="Use current_weather, then return one packing suggestion.",
model="demo-model",
output_type=PackingTip,
tools=("current_weather",),
idempotent_tools=("current_weather",),
budget=BudgetLimits(max_model_calls=2, max_tool_calls=1),
)
provider = FakeModelProvider(
ScriptedTurn.calling("current_weather", {"city": "Melbourne"}),
ScriptedTurn.returning({"suggestion": "Pack a light jacket."}),
)
stream = AgentRunner(provider=provider, tools=ToolRegistry((current_weather,))).stream(
agent, "What should I pack for Melbourne?", tenant="demo", user="local-user"
)
async for event in stream:
print(f"trace: {event.sequence} {event.kind}") # noqa: T201
print(await stream) # noqa: T201
if __name__ == "__main__":
asyncio.run(main())
The example contains 24 executable application statements; CI measures that ceiling so the first path cannot quietly grow into a framework of its own.
Expected shape:
trace: 0 run_started
...
trace: <n> tool_call_started
trace: <n> tool_call_finished
...
trace: <n> run_completed
... suggestion='Pack a light jacket.' ...
The PackingTip Pydantic model is the application contract. Invalid provider prose or a
wrong field fails as a typed schema error; the runtime does not parse, coerce, or invent a
replacement. FakeModelProvider is the only test-specific piece.
What the short example got for free¶
- The run records the agent, provider, tenant, acting user, usage, and every typed event.
BudgetLimitscaps model and tool calls before work is dispatched.- Tool arguments are validated and terminal rendering travels through the same redacted event surface used by telemetry.
- Provider, budget, guardrail, and schema failures are typed and fail closed; none becomes a plausible assistant answer.
3. Connect a live model¶
Choose the adapter that matches the wire protocol:
from tesserix_adk.core import ModelCapabilities
from tesserix_adk.models.providers import OpenAIProvider
model = "gpt-4.1-mini"
provider = OpenAIProvider(
model,
capabilities=ModelCapabilities(
tool_calling=True,
streaming=True,
context_window_tokens=128_000,
),
)
Set OPENAI_API_KEY in the process environment or inject a SecretProvider. Do not
put keys in adk.toml, source code, Agent metadata, gateway headers, or Agent Cards.
If the setting is absent, the typed ConfigurationError names OPENAI_API_KEY and points
back to the credential-free FakeModelProvider path before any HTTP request is attempted.
Replace only the fake:
runner = AgentRunner(
provider=provider,
tools=ToolRegistry((current_weather,)),
)
run = await runner.run(
agent,
"What should I pack for Melbourne?",
tenant="demo",
)
print(run.text)
await provider.aclose()
Prefer async with provider: when the provider lifecycle belongs to one block. Share a
provider or a configured client pool when one application serves many runs.
For Groq, xAI/Grok, OpenRouter, self-hosted models, and gateways, use the same runner with the configurations in Provider recipes.
4. Understand the two required declarations¶
An agent must choose exactly one model strategy:
model="model-id"calls the runner's direct provider; ortask_class="planning"lets a configured router select a provider/model.
It must also choose exactly one answer strategy:
free_text=Truefor prose; oroutput_type=YourPydanticModelfor a validated typed result.
These conditions fail at construction, not after the first provider call.
5. Keep the first production deployment small¶
Start with one agent and the fewest tools that solve the task. Before production:
- use a real tenant identifier and acting principal;
- set model and run deadlines;
- enable retries only for failures worth paying for again;
- declare every tool's idempotency and approval policy;
- add a shared idempotency store before effectful tool use;
- declare exact model capabilities and context/output limits;
- test provider failures and malformed tool calls offline;
- export redacted traces and measure tokens, cost, and latency;
- run the isolation and evaluation suites for the agent.
The detailed walkthrough is Build a custom agent. Continue with the cookbook for the agent, tool, budget, structured-output, and testing primitives introduced here. The repository's readiness findings and remaining protocol gaps are in the public-readiness review.
Optional: generate the first typed files¶
Inside an existing Python project with pyproject.toml, list the templates and generate
one agent without changing the project's layout or dependency manager:
tesserix-adk new --list
tesserix-adk new agent support-agent --template tool-using
uv run pytest -q test_support_agent.py
uv run mypy --strict support_agent.py support_tools.py test_support_agent.py
Every agent template uses TypedAgent[Input, Output], a bounded budget, resolved typed
configuration, run-rooted instrumentation, and an offline fake-provider test:
| Template | Added composition |
|---|---|
single |
One structured agent plus a separate schema-derived, read-only local tool |
tool-using |
The same safe baseline plus an explicit reusable ToolRegistry factory |
multi-agent |
A typed specialist plus an explicit Roster boundary for a supervisor |
mcp-client |
A local fallback tool and transport-neutral McpClient factory |
tesserix-adk new tool NAME generates a typed standalone tool and contract test. The
command validates every target before writing anything; an existing path aborts the whole
operation unless --force is explicit, and a failed replacement restores the prior bytes.
The generated dependency hint pins the installed kit version so a template never mixes API
eras with the runtime that created it.
CLI note¶
The package installs the project-qualified tesserix-adk command for self-contained
inspection and evaluation operations and never claims the ambiguous adk executable.
Use the Python API for application startup; python -m tesserix_adk.cli ... is equivalent.
Other helpers accept application-supplied storage/build callbacks and remain embedding
product surfaces rather than dispatcher commands.