Architecture
YAAAF is an artifact-first framework. The architecture is designed around one principle: artifacts flow through planned railways from sources to destinations. Agents are stations, not destinations.
System Overview
+------------------+ HTTP +------------------+
| Frontend | <-----------> | Backend |
| (Next.js) | | (FastAPI) |
+------------------+ +------------------+
|
v
+------------------+
| Orchestrator |
+------------------+
|
+------------------+------------------+
| |
v v
+------------------+ +------------------+
| Planner | | Workflow Engine |
| Agent | +------------------+
+------------------+ |
| v
v +------------------+
+------------------+ | Agents |
| YAML Workflow | --------------> | (execute in DAG |
| (DAG definition)| | order) |
+------------------+ +------------------+
|
v
+------------------+
| Artifact Storage |
+------------------+
Core Components
Orchestrator
The orchestrator is the entry point for all queries. It:
Receives the user query
Extracts the goal and determines target artifact type
Invokes the planner to generate a workflow
Passes the workflow to the workflow engine
Returns the final artifact to the user
Planner Agent
The planner generates YAML workflows from natural language goals:
Analyzes the user’s intent
Determines required artifact types
Selects appropriate agents
Constructs a valid DAG with dependencies
Uses RAG-based example retrieval for quality
Workflow Engine
The workflow engine executes the planned DAG:
Parses YAML workflow definition
Topologically sorts assets by dependencies
Executes agents in correct order
Passes artifacts between agents
Handles errors and retries
Artifact Storage
Centralized storage for all generated artifacts:
Tables (pandas DataFrames)
Images (PNG files)
Models (sklearn pickled models)
Text (documents, summaries)
JSON (structured data)
Artifacts are stored by unique ID and referenced throughout the workflow.
Data Flow
User Query: "Show sales by region as a chart"
|
v
+-------------------+
| Goal Extraction |
| Goal: visualize |
| Target: image |
+-------------------+
|
v
+-------------------+
| RAG Retrieval |
| Find similar |
| examples |
+-------------------+
|
v
+-------------------+
| Plan Generation |
| SqlAgent -> table |
| VisAgent -> image |
+-------------------+
|
v
+-------------------+
| Workflow Exec |
| Step 1: SqlAgent |
| Step 2: VisAgent |
+-------------------+
|
v
+-------------------+
| Final Artifact |
| Image: chart.png |
+-------------------+
Request Processing
Frontend: User submits query via chat interface
API: Backend receives POST to
/create_streamOrchestrator: Analyzes query, invokes planner
Planner: Generates YAML workflow using RAG examples
Engine: Executes workflow DAG
Agents: Process their assigned steps, produce artifacts
Storage: Artifacts stored with unique IDs
Streaming: Results streamed back as Notes
Frontend: Displays formatted response with artifacts
Agent System
Base Classes
ToolBasedAgent: For agents using the executor pattern
class ToolBasedAgent(BaseAgent):
def __init__(self, client, executor):
self._client = client
self._executor = executor
CustomAgent: For agents with complex custom logic
class CustomAgent(BaseAgent):
async def _query_custom(self, messages, notes):
# Custom implementation
pass
Executor Pattern
Agents delegate operations to executors:
class ToolExecutor:
async def prepare_context(self, messages, notes) -> dict
def extract_instruction(self, response) -> str
async def execute_operation(self, instruction, context) -> tuple
def validate_result(self, result) -> bool
def transform_to_artifact(self, result, instruction, id) -> Artefact
This pattern separates:
Agent: LLM interaction and reasoning
Executor: Tool-specific operations
Taxonomy System
Agents are classified by their role:
Role |
Description |
Examples |
|---|---|---|
EXTRACTOR |
Pull data from sources |
SqlAgent, DocumentRetrieverAgent |
TRANSFORMER |
Convert artifacts |
MleAgent, ReviewerAgent |
SYNTHESIZER |
Combine artifacts |
AnswererAgent, PlannerAgent |
GENERATOR |
Create final outputs |
VisualizationAgent, BashAgent |
Message Structure
Messages
class Messages:
utterances: List[Utterance]
class Utterance:
role: str # "user", "assistant", "system"
content: str
Notes
class Note:
message: str
artefact_id: Optional[str]
agent_name: Optional[str]
model_name: Optional[str]
internal: bool
Artifacts
class Artefact:
type: Types # TABLE, IMAGE, MODEL, TEXT, JSON
description: str
code: str # Source code or content
data: Any # Actual data
id: str # Unique identifier
Storage Architecture
ArtefactStorage
Singleton storage for all artifacts:
class ArtefactStorage:
def store_artefact(self, id: str, artefact: Artefact)
def get_artefact(self, id: str) -> Optional[Artefact]
def list_artefacts() -> List[str]
Artifacts are referenced by ID in agent responses:
<artefact type='table'>abc123</artefact>
API Endpoints
Backend API
Endpoint |
Method |
Description |
|---|---|---|
|
POST |
Create new conversation stream |
|
POST |
Get stream status and notes |
|
GET |
Retrieve artifact by ID |
|
POST |
Upload document for RAG |
|
GET |
Health check |
Frontend Architecture
Next.js Application
Server-side rendering
Real-time streaming via polling
TypeScript for type safety
Tailwind CSS for styling
Chat Interface
Message display with agent attribution
Artifact rendering (tables, images)
File upload support
Markdown rendering
Project Structure
yaaaf/
__init__.py
__main__.py
components/
agents/ # All agent implementations
base_agent.py # Base classes
orchestrator_agent.py
planner_agent.py
sql_agent.py
...
data_types/ # Core data structures
messages.py
artefacts.py
executors/ # Tool executors
sql_executor.py
python_executor.py
retrievers/ # RAG components
local_vector_db.py
planner_example_retriever.py
sources/ # Data source connectors
sqlite_source.py
rag_source.py
server/ # FastAPI backend
routes.py
run.py
data/ # Packaged data files
planner_dataset.csv
connectors/ # External integrations
mcp_connector.py
frontend/
apps/www/ # Next.js application
components/
app/
packages/ # Shared packages
Extensibility
Adding New Agents
Define taxonomy in
agent_taxonomies.pyCreate executor in
executors/Implement agent class extending
ToolBasedAgentRegister in
orchestrator_builder.py
Adding New Sources
Implement source class with required interface
Add type handling in configuration loader
Wire to appropriate agents
Adding New Artifact Types
Add type to
Artefact.TypesenumImplement serialization in storage
Add rendering support in frontend