Agent Factory¶
attune.agent_factory provides a universal factory for creating agents
and workflows across multiple frameworks through one common interface.
Pick your framework once, and the same create_agent / create_workflow
calls work whether the underlying agents are LangChain chains, LangGraph
state machines, AutoGen conversational agents, Haystack pipelines, or
Attune's native adapter.
The factory layers Attune-side features — model-tier routing, cost-tracking flags, optional resilience wrapping — on top of the chosen framework.
Supported frameworks¶
| Framework value | Adapter | Install |
|---|---|---|
Framework.NATIVE |
NativeAdapter (built-in) |
included |
Framework.LANGCHAIN |
LangChainAdapter (lazy) |
pip install langchain langchain-anthropic |
Framework.LANGGRAPH |
LangGraphAdapter (lazy) |
pip install langgraph langchain-anthropic |
Framework.AUTOGEN |
AutoGenAdapter (lazy) |
pip install pyautogen |
Framework.HAYSTACK |
HaystackAdapter (lazy) |
pip install haystack-ai |
Framework adapters are imported lazily — you only pay the import cost for
the one you use. Framework.NATIVE is always available.
If a framework isn't selected explicitly, AgentFactory picks one based
on what's installed and the use_case argument, falling back to
Framework.NATIVE.
Quick start¶
from attune.agent_factory import AgentFactory, Framework
# Create factory with your preferred framework
factory = AgentFactory(framework=Framework.LANGGRAPH)
# Create agents
researcher = factory.create_agent(
name="researcher",
role="researcher",
model_tier="capable",
)
writer = factory.create_agent(
name="writer",
role="writer",
model_tier="premium",
)
# Create workflow
pipeline = factory.create_workflow(
name="research_pipeline",
agents=[researcher, writer],
mode="sequential",
)
# Run (workflows are async)
result = await pipeline.run("Research AI trends in 2025")
print(result["output"])
framework= can be a Framework enum value or a string like
"langgraph" / "langchain" / "autogen" / "haystack" / "native".
The AgentFactory class¶
Constructor¶
AgentFactory(
framework: Framework | str | None = None,
provider: str = "anthropic",
api_key: str | None = None,
use_case: str = "general",
)
framework— explicit framework choice. IfNone, auto-selected from installed packages anduse_case(falls back toFramework.NATIVE).provider— LLM provider name. Defaults to"anthropic".api_key— API key string. If not provided, falls back to theANTHROPIC_API_KEYenv var (orOPENAI_API_KEYwhenprovider="openai").use_case— recommendation hint whenframeworkisNone. Valid values:"general","rag","multi_agent","code_analysis","workflow","conversational".
create_agent(...) -> BaseAgent¶
Creates an agent through the active adapter. Frequently used arguments:
| Argument | Type | Default | Notes |
|---|---|---|---|
name |
str |
required | Unique agent name (tracked for get_agent / list_agents) |
role |
AgentRole or str |
AgentRole.CUSTOM |
One of the values in AgentRole (see below) |
description |
str |
"" |
|
model_tier |
str |
"capable" |
"cheap", "capable", "premium" |
model_override |
str | None |
None |
Specific model ID, bypassing tier routing |
capabilities |
list[AgentCapability] | None |
None |
See AgentCapability below |
tools |
list[Any] | None |
None |
Framework-native tool objects (or what create_tool returns) |
system_prompt |
str | None |
None |
Custom system prompt |
temperature |
float |
0.7 |
|
max_tokens |
int |
4096 |
|
empathy_level |
int |
4 |
1–5; used by Attune-side features |
use_patterns |
bool |
True |
Load learned patterns (config flag) |
track_costs |
bool |
True |
Track API costs (config flag) |
memory_enabled |
bool |
True |
Conversation memory |
memory_type |
str |
"conversation" |
"conversation", "summary", "vector" |
resilience_enabled |
bool |
False |
Wraps result in a ResilientAgent (see below) |
Returns an object that implements BaseAgent — i.e. has
async def invoke(input_data, context=None) -> dict and
async def stream(input_data, context=None).
create_workflow(name, agents, mode="sequential", ...) -> BaseWorkflow¶
Creates a workflow from a list of agents.
mode—"sequential","parallel","graph", or"conversation". Which modes are actually supported depends on the active adapter (e.g."conversation"is most natural in AutoGen,"graph"in LangGraph).- Other arguments:
max_iterations=10,timeout_seconds=300,state_schema=None,checkpointing=True,retry_on_error=True,max_retries=3,framework_options=None.
Returns an object implementing BaseWorkflow —
async def run(input_data, initial_state=None) -> dict and
async def stream(input_data, initial_state=None).
create_tool(name, description, func, args_schema=None) -> Any¶
Creates a tool in the active adapter's native format. The exact return
type is adapter-specific; the default BaseAdapter implementation
returns a dict and individual adapters may override.
get_agent(name) -> BaseAgent | None / list_agents() -> list[str]¶
Look up an agent (or list names of agents) previously created on this factory instance. Agents are tracked by name inside the factory.
switch_framework(framework)¶
Switches the factory to a new framework. Clears the agent registry — existing agents created under the previous framework are not migrated.
list_frameworks(installed_only=True) (classmethod)¶
Returns a list of dicts describing frameworks. Each dict has
framework, installed, plus the fields from
framework.get_framework_info (name, description, best_for,
install_command, docs_url). When installed_only=False, all five
supported frameworks are returned regardless of installation status.
recommend_framework(use_case="general") (classmethod)¶
Returns a Framework enum value: the best-installed framework for the
given use case, or Framework.NATIVE if no preferred option is
installed.
Convenience constructors¶
Thin wrappers around create_agent with role + sensible tier defaults:
create_researcher(name="researcher", model_tier="capable", **kwargs)create_writer(name="writer", model_tier="premium", **kwargs)create_reviewer(name="reviewer", model_tier="capable", **kwargs)create_debugger(name="debugger", model_tier="capable", **kwargs)— also enablesAgentCapability.CODE_EXECUTIONcreate_coordinator(name="coordinator", model_tier="premium", **kwargs)
Pipeline helpers¶
create_research_pipeline(topic="", include_reviewer=True)— research → write → (review) sequential pipeline.create_code_review_pipeline()— security → debug → review sequential pipeline.
Enums¶
AgentRole¶
Built-in roles (string values shown):
COORDINATOR "coordinator"
RESEARCHER "researcher"
WRITER "writer"
REVIEWER "reviewer"
EDITOR "editor"
EXECUTOR "executor"
DEBUGGER "debugger"
SECURITY "security"
ARCHITECT "architect"
TESTER "tester"
DOCUMENTER "documenter"
RETRIEVER "retriever"
SUMMARIZER "summarizer"
ANSWERER "answerer"
CUSTOM "custom"
You can pass either the enum value (role=AgentRole.RESEARCHER) or the
lowercase string (role="researcher").
AgentCapability¶
CODE_EXECUTION "code_execution"
TOOL_USE "tool_use"
WEB_SEARCH "web_search"
FILE_ACCESS "file_access"
MEMORY "memory"
RETRIEVAL "retrieval"
VISION "vision"
FUNCTION_CALLING "function_calling"
Model tiers¶
model_tier is resolved by the adapter's get_model_for_tier, which
delegates to attune.routing.ModelRouter when available. The hard-coded
fallback for provider="anthropic" (used when the router is not
importable) maps:
| Tier | Fallback model (Anthropic) |
|---|---|
cheap |
claude-haiku-4-5-20251001 |
capable |
claude-sonnet-5 |
premium |
claude-opus-4-8 |
These IDs are fallback constants — the live mapping is whatever
ModelRouter resolves at runtime.
Optional wrappers¶
When you set the right flag on create_agent, the returned agent is
wrapped with:
ResilientAgent — Circuit breaker / retry / timeout¶
Enabled by resilience_enabled=True. Imported lazily from
attune.agent_factory.resilient; if the import fails, the flag is
logged and ignored (the underlying agent is returned unwrapped).
Tuning args: circuit_breaker_threshold (default 3),
retry_max_attempts (default 2), timeout_seconds (default 30.0).
Public exports¶
from attune.agent_factory import (
AgentCapability,
AgentConfig,
AgentFactory,
AgentRole,
BaseAdapter,
BaseAgent,
Framework,
WorkflowConfig,
)
That list is the __all__ of attune.agent_factory. ResilientAgent,
ResilienceConfig, and the framework-specific adapters are importable
from their submodules but not re-exported at the top level.
Example: code review pipeline¶
from attune.agent_factory import AgentFactory, AgentRole
factory = AgentFactory(framework="langgraph")
security = factory.create_agent(
name="security",
role=AgentRole.SECURITY,
model_tier="capable",
system_prompt="Analyze code for security vulnerabilities.",
)
quality = factory.create_agent(
name="quality",
role=AgentRole.REVIEWER,
model_tier="capable",
system_prompt="Review code quality and suggest improvements.",
)
coordinator = factory.create_agent(
name="coordinator",
role=AgentRole.COORDINATOR,
model_tier="premium",
system_prompt="Synthesize reviews into actionable feedback.",
)
pipeline = factory.create_workflow(
name="code_review",
agents=[security, quality, coordinator],
mode="sequential",
)
result = await pipeline.run("Review this code:\n<paste code here>")
print(result["output"])
The same code works with framework="langchain", "autogen",
"haystack", or "native" — the adapter handles the framework-specific
mechanics, and the call sites are identical.
Next steps¶
- Resilience patterns — deeper detail on
ResilientAgentconfiguration. - Reference index