AFramework is designed for building arbitrarily complex llm inference systems while abstracting away the underlying mechanisms required for high-performance execution. It provides a robust foundation for multi-agent orchestration, tool execution, and verifiable reasoning.
Recommended: use uv for install and sync (builds the C++ logger extension and service binary):
cd AFramework
uv syncPython code is used from the source tree (editable). When you change C++ under AFramework/logger/logger_cpp/, run uv sync again to rebuild.
Alternatively, with pip:
pip install -e .AFramework runs as a daemon that listens on a Unix socket (default /tmp/afr.sock). You do not need to start it manually for normal client use: the first time a client needs the control plane (BaseAgentCoreClient.execute_task / execute, cancel_task, get_health, or TaskCoreClient.submit), the library calls start_agent_framework() if the socket is not already responsive. Plugin modules are still registered lazily on that same path (only the modules your spec needs).
For a long-lived or explicitly managed daemon, you can still run AgentFramework yourself or call start_agent_framework() up front—see Usage Examples.
Use BaseAgentCoreClient for the default agent core. BaseAgentCore requires both a model backend and a verifier (see USAGE_EXAMPLES); BaseVerifier needs the same backend config nested under model_backend in the verifier spec.
import asyncio
from AFramework.agent_core import BaseAgentCoreClient
async def main():
model_backend = {
"model_backend_class_name": "VLLMBackend",
"model": "Qwen/Qwen3-30B-A3B-Thinking-2507",
# Optional: defaults to http://0.0.0.0:8005/v1 if omitted
# "base_url": "http://127.0.0.1:8005/v1",
}
client = BaseAgentCoreClient(agent_id="my_agent")
client.register_model_backend(**model_backend)
client.register_verifier(
verifier_class_name="BaseVerifier",
model_backend=model_backend,
max_verification_steps=20,
)
session_id = await client.execute_task(
messages=[{"role": "user", "content": "Hello world"}],
stream=True,
)
print(f"Task started with Session ID: {session_id}")
if __name__ == "__main__":
asyncio.run(main())AFramework uses Redis for resource control (rate limiting, circuit breaker) and the ToolPool. For non-default Redis:
Environment variables:
export REDIS_HOST=my-redis.example.com
export REDIS_PORT=6379
export REDIS_DB=0Or pass explicitly to AgentFramework:
from AFramework.aframework import AgentFramework
service = AgentFramework(
redis_host="my-redis.example.com",
redis_port=6379,
redis_db=0,
)Defaults: 127.0.0.1:6379 db=0 when not specified.
- API Reference – Comprehensive API documentation for clients, model backends, verifiers, TaskCore, batch processing, and more.
- Usage Examples – Patterns and examples for agentic tasks, MCP tools, batch processing, error handling, and configuration.
- Architecture Decision Records (ADRs) – Why we chose key designs; start with ADR 0001 — Phase 2.0 multi-tenant resources (tool names, resource keys, policies, MCP deferrals).
- Logging – Logger architecture and configuration.
- Stochastic Router – Router design and deferred features.
- ResourceManager – Resource control and future enhancements.
- Stochastic Task Router: Near-optimal routing via expected-latency minimization, task profiling (BOCPD), worker telemetry, and per-worker queues. See
implementation_plan_router.mdfor design details. - Multi-Process Architecture: True parallelism with isolated worker processes.
- Agentic Core: Flexible
AgentCoreabstractions for custom agent behaviors. The worker passes a canonical keyword bundle intoregister_task;model_backend,verifier, andmessagesmay be omitted on the wire (Noneat dispatch).BaseAgentCorestill requires those for its default loop; custom cores define their own contract (see Plugin Registration in the API reference). - MCP Support: First-class support for Model Context Protocol (MCP) servers.
- Verifiers: Integrated verification loops for robust reasoning and reduced hallucinations.
- Modular Backends: Swappable LLM backends (vLLM, OpenAI, Anthropic).
- Per-task fail-fast: Task and agent cores raise exceptions instead of returning
{"error": ...}blobs. Workers catch these per task, update Redis withtask_status=FAILEDand a structuredtask_error, and re-raise so only the individual coroutine fails while the worker process continues. - Structured
task_errorpayloads: Stored in Redis as:{"type": "<task_execution|internal_error|...>", "message": "<human readable>", "details": {...}, "traceback": "<optional traceback>"}.
- Client behavior:
BaseAgentCoreClient.get_task_result(session_id):- Raises
TaskExecutionErrorwhen the task failed (based ontask_statusandtask_error). - Raises
RuntimeErrorwhen the task is not yet completed or the result is missing. - Returns the normal result only when
task_status == COMPLETED.
- Raises
- Durability / late readers: Results and errors remain queryable via
AgentRunStoreuntil cleaned up (no special TTL). If a client dies, another client can later callget_task_result(session_id)and will see the same success result or raisedTaskExecutionError.
Deferred and optional work. Full specs and rationale are in the linked docs; the canonical checklist is also in todos.md at the repo root.
- MCP tenant integration — Per-tenant MCP URLs/headers/env, registry client keys, control-plane contract, tests. MCP_TENANT_INTEGRATION_TODO.md
Background: Stochastic_router_future.md — routing stack is production-ready; items below are enhancements.
- Await shutdown_response per worker before supervisor
join, or extend the drain window for large deployments. - Round-robin among fallback workers when retrying after enqueue failure (today uses
others[0]). -
AFW_CIRCUIT_COOLDOWN_Senvironment variable for circuit cooldown without code changes. - Prometheus metrics for circuit breaker / workers in cooldown (
get_metrics_for_pull/PrometheusMetricsBackend). - Optional: clearer documentation that cancel is best-effort for in-flight work.
Background: ResourceManager_future.md
- TTL on Redis keys (
afw:res:*,afw:circuit:*) with refresh on activity. - Redis authentication (password/username) and env vars + worker
redis_configbroadcast. - Redis URL as a single config string (
redis://...) with precedence over host/port. - Prometheus label escaping for resource keys containing quotes or backslashes.
- Wire
queue_statsintoMetricsBackend.format_snapshotand Prometheus (per-worker queue depth / backlog). - Per-resource metrics backend override on
ResourcePolicy(e.g. OTel vs Prometheus per key). - Sliding-window rate limiter as an alternative to the token-bucket algorithm.
- Denial metrics with tenant — Expose rate-limit / policy denial counters labeled by tenant where resource keys are tenant-qualified (e.g.
acme.openai:gpt-4), for per-tenant dashboards. Would extendResourceManager/MetricsBackend/ Prometheus paths as needed.
Production grade LLM inference engine.
