Core library to compose, validate, and run ADK agent systems from YAML.
Project description
Agent Compose Kit
Core Python library for YAML-driven construction of agent systems using Google ADK. This package provides configuration models, service factories, agent and tool builders, registries, runtime utilities, and a programmatic graph builder. It is designed to be consumed by external clients (CLI or web) that handle end-user interaction. No server, CLI, or TUI is included in this repo.
Features
- Config schema (Pydantic) with environment interpolation and provider defaults.
- Services (conservative defaults):
- Sessions: in-memory (default), Redis (host/port/db/password or URL), Mongo, SQL (database_url), YAML file.
- Artifacts: in-memory (default), Local folder, S3, Mongo, SQL.
- Memory: in-memory (default), Redis, Mongo, SQL, YAML file.
- Agents: direct model IDs (Gemini/Vertex) or LiteLLM models (OpenAI, Anthropic, Ollama, vLLM), function tools, sub-agent wiring.
- Workflows: sequential, parallel, loop composition.
- Runtime: map YAML runtime to ADK RunConfig; build ADK Runner instances.
- Public API for external CLIs: system/session helpers, run helpers, env-based path helpers.
Design notes
- Conservative by default: when required service parameters are not provided, factories fall back to in-memory implementations (never attempt network/local resources silently).
- Provider defaults:
model_providersmerge into LiteLLM configs (e.g., OpenAI keys, API base) without overwriting explicit values.
Tools
- Function tools:
{type: function, ref: "module:callable", name?}. The callable must be Python; for cross-language tools use MCP/OpenAPI below. - MCP toolsets: connect to MCP servers via stdio/SSE/HTTP and expose their tools to agents.
- OpenAPI toolsets: generate
RestApiTools from an OpenAPI spec (inline/path/url with allowlist); agents can call REST APIs directly. - Shared toolsets: define once under
toolsets:and reference from agents with{use: name}. - Registry references: reference MCP/OpenAPI toolsets declared under
mcp_registry/openapi_registryvia{use: 'mcp:<id>'},{use: 'mcp_group:<id>'},{use: 'openapi:<id>'},{use: 'openapi_group:<id>'}. - A2A remote agents: declare remote clients under
a2a_clientsand setAgentConfig.kind: a2a_remote+client: <id>.
YAML Examples (Tools)
toolsets:
# Reusable MCP toolset via stdio (requires `mcp` package installed)
fs_tools:
type: mcp
mode: stdio
command: npx
args: ["-y", "@modelcontextprotocol/server-filesystem", "./sandbox"]
tool_filter: [list_directory, read_file]
agents:
- name: planner
model: gemini-2.0-flash
instruction: Use tools when appropriate.
tools:
# Function tool (Python callable)
- {type: function, ref: tests.helpers:sample_tool, name: add}
# Reuse shared toolset
- {use: fs_tools}
- name: api_caller
model: gemini-2.0-flash
instruction: Use REST API tools.
tools:
- type: openapi
spec:
path: ./specs/petstore.yaml # or inline: "{...}" (json/yaml)
spec_type: yaml # json|yaml; inferred from path extension when omitted
tool_filter: []
# Registry references (resolved when registries are provided)
- {use: 'mcp:files'}
- {use: 'mcp_group:default'}
- {use: 'openapi:petstore'}
- {use: 'openapi_group:public'}
Requirements
- Python 3.12+
- Optional extras at runtime depending on backends:
- google-adk, google-adk-extras, litellm
- For MCP stdio mode:
mcppackage (and any server requirements)
Install
- pip:
pip install agent-compose-kit - uv:
uv add agent-compose-kit
Install (dev)
- uv sync
Quickstart (Programmatic)
from pathlib import Path
from agent_compose_kit.config.models import load_config_file
from agent_compose_kit.services.factory import build_session_service, build_artifact_service, build_memory_service
from agent_compose_kit.agents.builder import build_agents
from agent_compose_kit.runtime.supervisor import build_plan, build_run_config
cfg = load_config_file(Path("configs/app.yaml"))
print(build_plan(cfg))
artifact_svc = build_artifact_service(cfg.artifact_service)
session_svc = build_session_service(cfg.session_service)
memory_svc = build_memory_service(cfg.memory_service)
agents = build_agents(cfg.agents, provider_defaults=cfg.model_providers)
root = agents[cfg.workflow.nodes[0]] if (cfg.workflow and cfg.workflow.nodes) else agents[cfg.agents[0].name]
from google.adk.runners import Runner
runner = Runner(app_name="template-agent-builder", agent=root, artifact_service=artifact_svc, session_service=session_svc, memory_service=memory_svc)
rc = build_run_config(cfg)
# Use runner in your application according to ADK docs
Registries (Tools & Agents)
- Define reusable tools and agents in your config, then build registries:
from pathlib import Path
from agent_compose_kit.config.models import load_config_file
from agent_compose_kit.tools.builders import build_tool_registry_from_config
from agent_compose_kit.agents.builders_registry import build_agent_registry_from_config
cfg = load_config_file(Path("configs/app.yaml"))
tool_reg = build_tool_registry_from_config(cfg, base_dir=".")
agent_reg = build_agent_registry_from_config(cfg, base_dir=".", provider_defaults=cfg.model_providers, tool_registry=tool_reg)
root = agent_reg.get("parent") # or agent_reg.get_group("core")[0]
MCP/OpenAPI Registries (Config)
mcp_registry:
servers:
- id: files
mode: sse # sse|stdio|http
url: http://localhost:3000/sse
headers: {Authorization: 'Bearer ${TOKEN}'}
tool_filter: [list_directory, read_file]
groups:
- {id: default, include: [files]}
openapi_registry:
fetch_allowlist: ["api.example.com", "*.trusted.com"]
apis:
- id: petstore
spec: {path: ./specs/petstore.yaml} # or inline: "{...}" or url: https://api.example.com/openapi.json
spec_type: yaml
tool_filter: []
groups:
- {id: public, include: [petstore]}
A2A Remote Agents (Config)
a2a_clients:
- id: my_remote
# Prefer agent card URL (well-known path); url remains supported as a fallback
agent_card_url: https://remote.agents.example.com/.well-known/agent-card.json
headers: {Authorization: 'Bearer ${A2A_TOKEN}'} # optional
agents:
- name: remote
kind: a2a_remote
client: my_remote
model: gemini-2.0-flash # allowed but ignored by remote
Migration note (A2A)
- Prior releases used
urlas a base URL for a remote agent. The latest A2A wrapper prefers an agent card reference instead. - Use
agent_card_urlpointing to the remote agent’s well-known card (e.g.,/a2a/<name>/.well-known/agent-card.json). - The old
urlfield is still accepted and treated as an agent-card URL for backward compatibility.
Public API (for external CLI)
- Build a system and run a message:
from pathlib import Path
from agent_compose_kit.api.public import SystemManager, SessionManager, run_text, event_to_minimal_json
sm = SystemManager(base_dir=Path("./systems/my_system"))
cfg = sm.load("config.yaml")
runner, _resources = sm.build_runner(cfg)
import asyncio
async def main():
sess = await SessionManager(runner).get_or_create(user_id="u1")
async for ev in run_text(runner=runner, user_id="u1", session_id=sess.id, text="hello"):
print(event_to_minimal_json(ev))
asyncio.run(main())
Environment variables (optional)
AGENT_SYS_DIR: root directory where systems live (default./systems).AGENT_OUTPUTS_DIR: root directory for outputs/artifacts (default./outputs).AGENT_SESSIONS_URI: default sessions storage URI (defaultsqlite:///./sessions.db).
System Graph (Programmatic)
from pathlib import Path
from agent_compose_kit.config.models import load_config_file
from agent_compose_kit.graph.build import build_system_graph
cfg = load_config_file(Path("configs/app.yaml"))
graph = build_system_graph(cfg)
print(graph["nodes"], graph["edges"]) # nodes/edges dicts
YAML Example
services:
session_service: {type: in_memory}
artifact_service: {type: local_folder, base_path: ./artifacts_storage}
agents:
- name: planner
model: gemini-2.0-flash
instruction: You are a helpful planner.
tools: []
workflow:
type: sequential
nodes: [planner]
runtime:
streaming_mode: NONE
max_llm_calls: 200
Testing
- Run all tests:
uv run --with pytest pytest -q - Current coverage includes config/env interpolation, service factories (with in-memory fallbacks), function tool loading, workflow composition, and RunConfig mapping.
- Cloud-backed integrations (e.g., GCS) are skipped unless credentials are configured.
Development
- Lint:
uv run --with ruff ruff check . - Format:
uv run --with ruff ruff format . - Tests:
uv run --with pytest pytest -q
Project Structure
src/config/models.py— Pydantic models, env interpolation, example writer.src/services/factory.py— session/artifact/memory service builders.src/agents/builder.py— model resolution (string/LiteLLM), function tools, sub-agent wiring.src/tools/loader.py— unified loader for function/MCP/OpenAPI tools and shared toolsets.src/tools/registry.py— global ToolRegistry (ids, groups, caching, close_all).src/agents/registry.py— global AgentRegistry (ids, groups, sub-agent wiring).src/agents/builders_registry.py— helpers to build AgentRegistry from AppConfig.src/tools/builders.py— helpers to build ToolRegistry from AppConfig.src/tools/mcp_registry.py— McpRegistry for building/caching MCP toolsets.src/tools/openapi_registry.py— OpenAPIRegistry for building/caching OpenAPI toolsets.src/registry/fs.py— filesystem helpers for saving/loading systems.src/api/public.py— public API for external CLIs (SystemManager, SessionManager, run helpers).src/paths.py— path/env helpers (AGENT_SYS_DIR, AGENT_OUTPUTS_DIR, AGENT_SESSIONS_URI).
Schema & Registry
- Export AppConfig JSON schema programmatically:
from agent_compose_kit.config.models import export_app_config_schema
- Save/load system configs:
from agent_compose_kit.registry.fs import save_system, load_system, list_systems, list_versions, promote
src/runtime/supervisor.py— plan summary, Runner construction, RunConfig mapping.templates/app.yaml— example config template.
Roadmap
- See
FULL_IMPLEMENTATION_PLAN.mdfor detailed milestones (MCP/OpenAPI toolsets, JSON Schema export, registry helpers, observability hooks).
Optional Dependencies
mcpfor MCP stdio moderequestsfor OpenAPI URL fetching (when usingspec.url)
Service Config: URI vs dict
services:
# URI strings are accepted and parsed into structured configs
session_service: "sqlite:///./sessions.db" # or "redis://localhost:6379/0", "mongodb://localhost/adk"
artifact_service: "file://./artifacts" # or "s3://my-bucket/prefix", "sqlite:///./artifacts.db"
# memory service optional
# memory_service: "redis://localhost:6379/0"
Equivalent programmatic usage:
from agent_compose_kit.services.factory import build_session_service, build_artifact_service
session = build_session_service("sqlite:///./sessions.db")
artifacts = build_artifact_service("file://./artifacts")
License MIT
Publishing plan (summary)
- Finalize metadata in
pyproject.toml: project name, description, license, classifiers, homepage/repo URLs, keywords. - Optional extras: define
[project.optional-dependencies]fortoolsanddev. - Versioning: adopt SemVer; tag releases in VCS (e.g., v0.1.0).
- Build:
python -m build(ensurebuildin dev deps) oruv build. - Publish:
twine upload dist/*(or GitHub Actions workflow for publish-on-tag). - Docs: keep README as long_description; ensure
README.mdrenders on PyPI. - CI: add GitHub Actions for lint/test on PR; optional publish job on tag.
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
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 agent_compose_kit-0.5.0.tar.gz.
File metadata
- Download URL: agent_compose_kit-0.5.0.tar.gz
- Upload date:
- Size: 38.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.8.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e36d2f366d97b7103f40a401d3fc45eb8382a43d5ca8f34dcf713702bf1cef5d
|
|
| MD5 |
e0eaf3d4feb67aff043b520b93247a63
|
|
| BLAKE2b-256 |
762544d27eff5a14121b96c4c7686b080e10da1b4ab31413e7b9d103679e8d4a
|
File details
Details for the file agent_compose_kit-0.5.0-py3-none-any.whl.
File metadata
- Download URL: agent_compose_kit-0.5.0-py3-none-any.whl
- Upload date:
- Size: 52.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.8.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
beb68c88ac68d8831d4c3f45291975171a4efb940b30b89fd92271d43c8f669d
|
|
| MD5 |
311fb8a144d8b6e6b5db08c47cb7efa7
|
|
| BLAKE2b-256 |
631297d6ce10fade4295dd05daf2609587ae5f3154b24c3656c8f1786c2807c9
|