Skip to content

About

No description or website provided.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

Blueprint Agents

PyPI version Python 3.13+ License: MIT CI

A Python framework for building production-ready AI agent microservices with event-driven architecture.

Blueprint Agents gives you a component-based toolkit for building intelligent microservices that process events, call LLMs, expose REST APIs, and run scheduled tasks -- all wired together with a fluent builder API and backed by production-grade observability.


Key Features

  • Component Architecture -- Five composable base classes (EventHandlerBase, ServiceBase, RestApiBase, AgentRuntime, SchedulerBase) assembled via a fluent AppBuilder
  • Event-Driven Processing -- CloudEvents v1.0 with chain-of-responsibility handlers, Dapr and NATS pub/sub support; on NATS, concurrent runs per agent with JetStream heartbeats and run timeouts, and named connections (several brokers or accounts per agent, supplied by a connection source)
  • LLM Integration -- AI agents powered by Pydantic AI with structured outputs, tool calling, and multi-model support (OpenAI, vLLM)
  • Built-in Observability -- OpenTelemetry tracing, metrics, and structured logging out of the box
  • Multi-Agent Grouping -- Run one agent per process, or host several in one process, as a deployment choice: the agent's code is identical either way
  • CLI Scaffolding -- Generate complete project structures and individual components with the asbs CLI
  • Deployment Ready -- Docker, Kubernetes with Helm charts, health checks, and CI/CD patterns included

Quick Start

# Install the framework
pip install avs-blueprint-agents

# Scaffold a new project -- asbs setup writes into the current directory
mkdir my-agent && cd my-agent
asbs setup my-agent

# Start developing
pip install -e .
asbs dev

Your service is now running at http://localhost:8000 with interactive API docs at /docs, and this agent's routes under /api -- served alone, at the root. asbs dev --name my_agent serves it under the namespace a group image would give it, with its routes under /api/my_agent.

asbs setup writes your project's main.py as a declaration -- an AppBuilder that is never built -- and a create_app() that builds it. It writes no agents.toml: that map belongs to an image that hosts several agents. That is what lets the same project run on its own and be hosted alongside other agents without changing a line. See Running one agent, or several.


Installation

Stable Release (PyPI)

pip install avs-blueprint-agents

Or with uv:

uv add avs-blueprint-agents

Alpha Release (TestPyPI)

Alpha builds are published to TestPyPI. TestPyPI must be used for this package only -- it also carries stale copies of common dependencies (an ancient fastapi, an apscheduler too old for this package), and any setup that lets the resolver reach them for dependencies fails.

With uv, name the index for this one package and nothing else:

[[tool.uv.index]]
name = "test-pypi"
url = "https://test.pypi.org/simple/"
explicit = true                                    # only for packages that name it below

[tool.uv.sources]
avs-blueprint-agents = { index = "test-pypi" }
uv add "avs-blueprint-agents==0.9.0a1"

explicit = true is the load-bearing part: without it uv applies its default first-index strategy, pins every dependency to the first index that happens to contain it, and the resolution fails on TestPyPI's old apscheduler. That is deliberate protection against dependency confusion, not something to work around with --index-strategy unsafe-best-match.

pip has no equivalent -- no index priority and no per-package source, so --extra-index-url merges both indexes and the broken copies stay reachable whichever order the flags are in. Fetch the package alone, then install it with dependencies resolved from PyPI:

pip download --no-deps --index-url https://test.pypi.org/simple/ "avs-blueprint-agents==0.9.0a1" -d ./dl
pip install --index-url https://pypi.org/simple/ ./dl/avs_blueprint_agents-0.9.0a1-py3-none-any.whl

Pin the exact alpha version in both cases: PyPI carries the newer stable release, and an unpinned install resolves to that instead.

From Source

git clone https://github.com/2SpeakAI/blueprint-agents.git
cd blueprint-agents
pip install -e ".[dev]"

How It Works

Blueprint Agents uses five composable component types, wired together with the AppBuilder:

from blueprint.agents import AppBuilder

from .handlers.order_handler import OrderHandler
from .services.order_service import OrderService
from .api.routes import OrderApi

agent = (
    AppBuilder()
    .with_handler(OrderHandler)
    .with_service(OrderService)
    .with_rest_api(OrderApi)
    .with_cache()
)

Two things about that chain are worth knowing up front:

  • Nothing is constructed yet. Every with_* call records a declaration; build() constructs it. Leaving build() out is what lets the deployment decide the configuration and the namespace each component is built in.
  • Pass classes, not instances. with_rest_api(OrderApi) rather than with_rest_api(OrderApi()). An instance created on the with_* line exists before any namespace does, so it belongs to the process root for ever. A group refuses them, and so do agent.build(config) and the create_app() that calls it; only the old AppBuilder(config)...build() shape still accepts them.

The Five Components

Component Base Class Purpose
Event Handler EventHandlerBase Route CloudEvents (priority chain) and translate each into one service call; returns a result, HandlerResult.skipped(reason) or None
Service ServiceBase All business logic, including whether an event needs work; runs the agents
REST API RestApiBase Define HTTP endpoints with @get(), @post(), @put(), @delete(), @patch() decorators
Agent AgentRuntime Run LLM agents with structured outputs, tool calling, and prompt management
Scheduler SchedulerBase Execute cron-based background tasks with auto-registered trigger endpoints

Component Lifecycle

All components follow a consistent lifecycle managed by the framework:

__init__()     -->  Register with component registry
on_startup()   -->  Resolve dependencies, connect to external services
[running]      -->  Process events, handle requests, run tasks
on_shutdown()  -->  Clean up resources, close connections

Running one agent, or several

How many agents share a process is a deployment parameter, not an architectural commitment. The declaration in your project's main.py is the same either way; only what starts the process differs.

Shape What starts it
Standalone, a module-level app you built yourself uvicorn src.main:app
Standalone, a declaration built by a factory uvicorn src.main:create_app --factory
Hosted -- one agent, or twenty python -m blueprint.agents.entrypoint

Standalone

Unchanged, and still fully supported. Build the declaration yourself and serve it:

config = Config(settings_files=["settings.toml", ".secrets.toml"])
app = agent.build(config)          # the declaration from "How It Works"

A standalone agent runs at the root namespace: its registry names, REST paths (/api/...), NATS queue group, JetStream durable and OpenTelemetry service.name are exactly what they were before this existed. Nothing reads agents.toml unless you run the entry point.

Hosted in a group

Name each agent, its directory (root, relative to the image root) and the module its declaration lives in, in the image's agents.toml. Both keys are required:

[agents.orders]
root   = "agents/orders"
module = "agents.orders.src.main:agent"

[agents.billing]
root   = "agents/billing"
module = "agents.billing.src.main:agent"

The image contains those agents; the deployment decides which of them a given process runs:

docker run -e BLUEPRINT_AGENTS=orders,billing my-image      # both in one process
docker run -e BLUEPRINT_AGENTS=orders my-image              # a group of one

Each hosted agent gets its own handlers, agent runtime, REST routes, AI client, thread pool, caches and broker connection. The port, the health endpoint and the process are shared. Agents in one process are isolated: an agent resolves its own components, caches and configuration and the root's shared ones, and the framework refuses any attempt to reach a neighbour's.

A group of one gives today's process isolation; a group of twenty gives the shared-interpreter memory profile. Moving an agent between groups changes neither its broker-side consumer identity nor its telemetry identity.

The agent's name in agents.toml is its identity everywhere else -- registry prefix, NATS queue group, part of the JetStream durable, cache partition, OpenTelemetry service.name and the REST prefix /api/<name>. Renaming it after the first deploy is a consumer migration, not a rename. Choose it before you ship.

Other group settings: BLUEPRINT_GROUP_CONFIG and BLUEPRINT_GROUP select a named group from a mounted file, and BLUEPRINT_CRITICAL_AGENTS says which agents failing should fail the process. See the Multi-Agent Setup guide for the full reference and the migration path for an existing single-agent project.


Examples

Explore complete, runnable examples in the examples/ directory:

Example Description Components Used
inventory_api Product inventory CRUD REST API RestApiBase, ServiceBase, Cache
order_event_pipeline E-commerce order processing with Dapr pub/sub EventHandlerBase, ServiceBase, Dapr
document_summarizer LLM-powered document summarization with structured output AgentRuntime, AgentBuilder, Tools
webhook_relay Webhook ingestion and normalization pipeline with NATS EventHandlerBase, NATS, Cache
health_monitor System health monitoring with scheduled checks SchedulerBase, ServiceBase, Cache

Configuration

Blueprint Agents uses Dynaconf for hierarchical configuration via TOML files:

settings.toml (checked into version control):

[default]
app_name = "my-agent"
app_port = 8000
event_bus = "dapr"          # "dapr", "nats", or "sessions"
log_level = "INFO"

[default.runtimes.my_agent]
model_provider = "openai"
model_name = "gpt-4o-mini"
model_max_tokens = 1000
model_temperature = 0.3

[default.cache]
cache_dir = ".cache/my-agent"
default_ttl = 3600

.secrets.toml (never commit this file):

[default.runtimes.my_agent]
model_api_key = "sk-your-api-key"

For the sessions transport (consumes SSE jobs from service-sessions):

[default]
event_bus = "sessions"

[default.sessions_service]
base_url = "http://sessions:8000"
agent_id = "my-agent"
agent_type = "analyser"
capabilities = ["analyse_documents"]
api_key = "@format {env[SESSIONS_API_KEY]}"
# Optional per-agent HS256 bearer token. When set, sent as `Authorization: Bearer <token>`
# alongside `X-Api-Key` on the gated sessions routes (register, SSE stream, session-key fetch).
# To opt out, OMIT this line entirely (ungated sessions, X-Api-Key only). Do NOT keep the line
# with SESSIONS_AGENT_TOKEN undefined — Dynaconf fails config load on an unresolved `@format`.
agent_token = "@format {env[SESSIONS_AGENT_TOKEN]}"
max_concurrent_jobs = 5
job_timeout_seconds = 300

The bearer is only sent when agent_token is configured, so agents keep working against ungated sessions and can be rolled out before the gate is flipped. The token is an offline-minted HS256 JWT whose sub equals the agent's agent_id and whose caps claim is its capability ceiling (see service-sessions#198/#326). Never commit the token value — inject it via the SESSIONS_AGENT_TOKEN environment variable (e.g. YOUR_AGENT_TOKEN).

Opting out cleanly: because the value above is a Dynaconf @format interpolation, keeping the agent_token line while SESSIONS_AGENT_TOKEN is undefined raises DynaconfFormatError at config load — the agent won't start. To run against ungated sessions, either omit the line entirely or export an empty SESSIONS_AGENT_TOKEN= (both yield X-Api-Key-only behaviour).

The token is read once at startup (like api_key) and is not hot-reloaded. If the JWT carries an exp, mint it long-lived enough to outlast the agent process and restart the agent to roll a renewed token — an expired bearer makes the gated routes return 401/403, and the SSE consumer will reconnect-and-retry with the same stale token until it is restarted.

No SessionsBus, SessionsApiClient, or SessionKeyProvider references in service main.py — AppBuilder.build() wires them automatically.

See the Configuration Reference for all available settings.


CLI Reference

The asbs CLI scaffolds projects and components:

asbs setup <project-name>                         # Create a new agent, in the current directory
asbs setup --group                                # Create an image's files (agent map, group Dockerfile)
asbs create handler <name> [--event-type <type>]  # Add an event handler
asbs create service <name>                        # Add a business service
asbs create api <name>                            # Add a REST API
asbs create agent <name>                          # Add an AI agent
asbs create scheduler <name> [--cron <expr>]      # Add a scheduler
asbs validate [--group]                           # Validate one agent, or a whole image
asbs dev [--name <agent>] [--port <port>]         # Run development server
asbs docs [<topic>] [--cat]                       # Locate the bundled documentation
asbs claude                                       # Install the Claude Code files into a project

See the full CLI Reference.


Deployment

Blueprint Agents services deploy as standard Python containers:

  • Docker -- Multi-stage Dockerfile included with scaffolded projects
  • Kubernetes -- Helm charts with Dapr sidecar injection, health probes, and ConfigMap/Secret management
  • CI/CD -- GitHub Actions workflows for linting, testing, and publishing

See the Deployment Guide for detailed instructions.


Documentation

The documentation ships with the package. Every page below is installed alongside the code, so a developer -- or an AI assistant working in your project -- can read it without network access:

asbs docs                                      # list every page
asbs docs guides/multi-agent-setup             # print the path to one page
asbs docs reference/configuration-keys --cat   # print its contents

asbs claude additionally installs Claude Code skills that route to the right page for the task at hand. The links below are the same pages on GitHub, for browsing.

Getting Started

Core Concepts

  • Architecture -- Component model, registry, and lifecycle
  • Event Processing -- CloudEvents, handler chain, Dapr/NATS
  • Configuration -- Settings, secrets, and environment variables
  • Caching -- Disk and Redis caches, TTL, namespaces, and per-agent isolation
  • Observability -- OpenTelemetry tracing, metrics, and logging

Component Guides

Operations

Reference


Requirements

  • Python 3.13+
  • Docker (optional, for containerized deployment)
  • Dapr CLI (optional, for Dapr pub/sub event processing)
  • NATS Server (optional, for NATS event processing)
  • API keys for AI providers (optional, only for LLM agent features)

Contributing

We welcome contributions! See CONTRIBUTE.md for guidelines on:

  • Setting up the development environment
  • Running tests and linting
  • Submitting pull requests

License

This project is licensed under the MIT License. See LICENSE for details.

About

No description or website provided.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages