Reference agents package for the TAI ecosystem: opt-in, manifest-loaded generic agents built on the deepagents/LangGraph runtime.
Project description
tai42-agents
The reference agents package for the TAI ecosystem — an opt-in, manifest-loaded collection of generic agents built on the deepagents/LangGraph runtime.
Every agent here registers through the tai42_app handle from tai42_contract.app
and is loaded by the host from the manifest (agents[].module). Its only tai-*
dependencies are tai42-contract (the Agent ABC, the StreamEvent taxonomy,
and the tai42_app handle it registers through) and tai42-kit (settings
machinery and the llm factories model access goes through). It never
imports the skeleton — tai42-agents is contract-facing.
The TAI ecosystem
TAI is an open-source runtime for MCP tools, agents, and workflows. An agent is a capability the runtime hosts and exposes as a tool; the seven here are the platform's ready-made, batteries-included set. This repo is their per-agent reference doc home; the documentation site covers using them and the platform-level story:
- Use the ready-made agents (guide): https://tai42.ai/guides/use-the-ready-made-agents
- Agents concept: https://tai42.ai/concepts/agents
- Ecosystem catalog: https://tai42.ai/reference/catalog
Install
Requires Python 3.13+. Nothing is on PyPI yet, so install from source — clone
this repo alongside your tai42-skeleton checkout and add it as an editable
dependency of the environment that runs the server:
git clone https://github.com/tai42ai/tai-agents
cd tai-skeleton # or your own app checkout
uv add --editable ../tai-agents # once published: uv add tai42-agents
The agent runtime (deepagents, langgraph, langchain-core, langchain,
pydantic, pydantic-settings, fastmcp, opentelemetry-api, wcmatch) is a
base dependency — agents are this package's purpose, so there is no runtime extra
to opt into. Model-provider SDKs are never direct dependencies here: model
access goes through tai42-kit's llm factories, configured per deployment.
Registering an agent
An agent is a class subclassing the contract Agent ABC, registered under a
name with the @tai42_app.agents.agent(name) decorator. Registration fires when
the module imports (import-to-register); the host imports the module because
the manifest names it:
agents:
- title: my-agents
module: tai42_agents.<module>
# include: [<agent name>] # optional — omit to expose all agents in the module
from pydantic import BaseModel
from tai42_contract.agent import Agent
from tai42_contract.app import tai42_app
class EchoInput(BaseModel):
user_message: str = ""
@tai42_app.agents.agent("echo")
class EchoAgent(Agent):
tool_name = "echo"
tool_description = "Echoes the user message back."
ToolInput = EchoInput # a JSON-able pydantic model of the tool params
async def run(self, *, user_message: str = "", **kwargs):
return user_message
Registration gives each agent two faces, both derived from the one class:
- an in-process
astreammethod (API / SSE facing) that yields the contract'sStreamEventtaxonomy (ReasoningStep,ToolCallStep/ToolResultStep,MessageDelta,MessageFinal,RunUsage,StructuredFinal,InterruptFinal); - an auto-generated JSON
runtool (LLM / MCP / flow-engine facing) whose signature is the agent'sToolInputmodel.
Agents
The package ships seven agents, each in its own module so a manifest can load exactly the ones a deployment wants:
tools_agent(tai42_agents.tools_agent) — the plain/advanced LangGraph tools agent. Uniform tool inputs:tool_names(client tools resolved through the app registry), livetools, andpresets(a base tool bound to fixed kwargs; a sub-flow isbase_tool="flow"withfixed_kwargs={"flow_graph": ...}).deep_agent(tai42_agents.deep_agent) — a deepagents-harness agent: planning, a per-thread scratch filesystem, skills (served live from the template provider or supplied inline), one level of nested subagents, and human-in-the-loop interrupts with resume via a LangGraphCommand. Both faces fail loudly when a requestedresponse_formatproduces no structured output: the invoke face raises on drain, and the stream face raises after the stream drains (a pending interrupt takes precedence over the raise).retrieval_tools_agent(tai42_agents.retrieval_tools_agent) — a tools agent that does not bind every tool to the model up front: it embeds each tool's description into a vector store and exposes aretrieve_toolssemantic-search tool, binding matches on demand until the model emits a terminal{"status": ...}object. Useful when the tool set is large.mcp_tools_agent(tai42_agents.mcp_tools_agent) — a tools agent whose tools come from an MCP server: it opens afastmcpclient from a caller'smcpServersconfig, converts those tools to LangChain tools, and runs with the client held open. Withinject_env=True, only the environment variable names listed inenv_allowlistare copied fromos.environinto each server'senv(the server's ownenvwins on conflict);inject_env=Truewith an empty or missingenv_allowlistis a malformed request and raisesValueErrorrather than silently injecting nothing.mcp_tools_agentis admin-curated — expose it ONLY to trusted, access-controlled callers/agents, NEVER to an agent that processes untrusted content.voting_agent(tai42_agents.voting_agent) — runs N voter LLMs in parallel over one prompt, then a judge LLM decides by majority vote (breaking ties with its own reasoning). Returns aVotingOutput; only the judge streams.refine_agent(tai42_agents.refine_agent) — an Evaluator↔Critic loop: the evaluator drafts, the critic reviews, and they alternate until the critic emits the approval token or the iteration budget is exhausted (a loudRuntimeError, never an unapproved draft). Only the final approved pass streams.vqa_agent(tai42_agents.vqa_agent) — visual question answering: a single multimodal completion over animage_urland aquery. No tools, no graph.
Expose kwargs-carrying agents to trusted callers only. base_url/api_key
in llm_kwargs/embedding_kwargs legitimately route to a caller-chosen
model/embedding endpoint; expose any agent or tool carrying these kwargs only to
trusted callers — an injected parent agent could redirect the model/embedding
call to a hostile endpoint and leak the key/context.
Wire the ones you want in the manifest — one agents: entry per module, each
with a title; add include: to expose a subset of a module's agents:
agents:
- title: tools-agent
module: tai42_agents.tools_agent
- title: deep-agent
module: tai42_agents.deep_agent
- title: retrieval-tools-agent
module: tai42_agents.retrieval_tools_agent
- title: mcp-tools-agent
module: tai42_agents.mcp_tools_agent
- title: voting-agent
module: tai42_agents.voting_agent
- title: refine-agent
module: tai42_agents.refine_agent
- title: vqa-agent
module: tai42_agents.vqa_agent
Import rule
The shipped tai42_agents package imports tai42-contract, tai42-kit, and the
agent runtime (deepagents / langgraph / langchain-core / langchain /
pydantic / fastmcp / opentelemetry / wcmatch) — the declared
dependencies and their resolved dependency closure — plus the standard
library. It never imports tai42-skeleton, which sits a layer above, and never
reaches for a package that is not a dependency of the shipped wheel. The rule is
enforced twice: ruff (flake8-tidy-imports bans) fails lint on a skeleton
import, and an import-graph test asserts every root in the module graph is on
the allowlist — once by importing every shipped module in a fresh subprocess and
inspecting sys.modules, and once by parsing every shipped source file, so an
import nested in a function body, a class body, or a TYPE_CHECKING block is
caught too.
Development
uv sync --extra dev
uv run ruff check
uv run ruff format --check
uv run pyright
uv run pytest
[tool.uv.sources] resolves tai42-contract and tai42-kit from sibling
checkouts for local development; the published wheel floors them from the
index.
Dependency install is plain. The deepagents/LangGraph stack (deepagents,
langgraph, langchain-core, langchain, pydantic, opentelemetry-api,
fastmcp) installs as ordinary locked wheels via uv sync; CI runs
uv sync --locked with no extra path setup.
License
Apache-2.0. See LICENSE and NOTICE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file tai42_agents-0.1.0.tar.gz.
File metadata
- Download URL: tai42_agents-0.1.0.tar.gz
- Upload date:
- Size: 80.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.18 {"installer":{"name":"uv","version":"0.11.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c9e0ea4f8d8cd4ca64d05f8808d2bad94ad60b245cba433e33421e2c484b5200
|
|
| MD5 |
7eb022cb07e9ed44714d1fa1e7492297
|
|
| BLAKE2b-256 |
7cbdc9f4cb4ba84d2623831d312f46188996b4fe99aaee59f4155de28f99ef0c
|
File details
Details for the file tai42_agents-0.1.0-py3-none-any.whl.
File metadata
- Download URL: tai42_agents-0.1.0-py3-none-any.whl
- Upload date:
- Size: 94.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.18 {"installer":{"name":"uv","version":"0.11.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9afc7cec4dcb501271e79ef94a23b3bb5e9e9b656a279600be3995241b563600
|
|
| MD5 |
87335db74819521a715ecc0fcccc20de
|
|
| BLAKE2b-256 |
737b6e3736d940adf69792ae0bc82b531dbf0017f91ac96899a84bedbd7a8e8f
|