Usage
Overview
Fabricatio is a streamlined Python library for building LLM applications using an event-based agent structure. It features:
Event-Driven Architecture: Robust task management through an EventEmitter pattern
LLM Integration & Templating: Seamlessly interact with large language models and dynamic content generation
Async & Extensible: Fully asynchronous execution with easy extension via custom actions and workflows
Basic Example
Here’s a simple “Hello World” example:
"""Example of a simple hello world program using fabricatio."""
from typing import Any
# Import necessary classes from the namespace package.
from fabricatio import Action, Event, Role, Task, WorkFlow, logger
# Create an action.
class Hello(Action):
"""Action that says hello."""
output_key: str = "task_output"
async def _execute(self, **_) -> Any:
ret = "Hello fabricatio!"
logger.info("executing talk action")
return ret
# Create the role and register the workflow.
Role.with_bio().subscribe(Event.quick_instantiate("talk"), WorkFlow(name="talk", steps=(Hello,))).dispatch()
# Make a task and delegate it to the workflow registered above.
assert Task(name="say hello").delegate_blocking("talk") == "Hello fabricatio!"
Async Usage
For asynchronous execution:
import asyncio
from fabricatio import Action, Role, Task, logger, WorkFlow, Event
from typing import Any
class Hello(Action):
output_key: str = "task_output"
async def _execute(self, **_) -> Any:
return "Hello fabricatio!"
async def main() -> None:
role = Role.with_bio().subscribe(
Event.quick_instantiate("talk"),
WorkFlow(name="talk", steps=(Hello,))
).dispatch()
result = await Task(name="say hello").delegate("talk")
logger.success(f"Result: {result}")
if __name__ == "__main__":
asyncio.run(main())
Delegation Modes
Fabricatio provides two delegation modes:
delegate()(async, non-blocking): Returns aTaskhandle. Use this when you need to run multiple tasks concurrently or want to avoid blocking the event loop.delegate_blocking()(sync): Blocks until the task completes. Use this in synchronous contexts or simple scripts where concurrency is not needed.
Fire-and-forget: You can call delegate() and discard the result if you only
need to trigger the side effect. The task will still be processed by the Role.
Why async matters: Concurrent task execution lets you interleave LLM calls, database queries, and external API requests without blocking the event loop. This is critical for chat loops, streaming responses, and real-time applications where latency must be kept low.
Usage Scenarios
Fabricatio supports various usage scenarios:
- Simple Chat
Interactive conversational loop. Demonstrates
Actionas a stateful chat handler — each turn appends to conversation history, and the workflow persists context across interactions.- Retrieval-Augmented Generation (RAG)
Retrieves relevant documents before the LLM call. Shows how
Actions compose external data (embeddings, vector DB) with generation — the retrieval step feeds context into the prompt step.- Article Extraction
Parses and injects structured data into vector databases. Demonstrates multi-step pipelines: fetch, parse, chunk, embed, and store — each a separate
Action.- Propose Task
LLM-driven task decomposition from natural language. The LLM analyses a user request and breaks it into sub-tasks, each of which can be dispatched as a new workflow.
- Code Review
Demonstrates the review→correct workflow pattern: review code, collect feedback, then apply corrections in a follow-up action — all within the same workflow.
- Write Outline
Demonstrates structured output generation with typst formatting. The
Actionreturns a structured schema that is rendered into a formatted document.
For detailed examples and advanced usage patterns, explore the examples/ directory in the repository.
Key Concepts
- Actions
The basic unit of work in Fabricatio. Each action performs a specific task and can be chained together. Why: Encapsulate LLM calls and side effects so they’re composable and testable.
- Workflows
A sequence of actions that define how tasks are processed. Why: Chain actions into deterministic pipelines — each step’s output feeds the next.
- Events
Triggers that initiate workflows. Events follow an event-driven architecture pattern. Why: Decouple task submission from execution — the same event can trigger different workflows in different Roles.
- Roles
Entities that manage workflows and handle task delegation. Why: Own workflows and LLM configuration, enabling different agents with different capabilities.
- Tasks
Work items that get processed through workflows. Why: Carry state through a workflow, track dependencies, and support cancellation.
Getting Started
Install fabricatio with desired capabilities
Define your actions by subclassing
ActionCreate workflows combining your actions
Register workflows with roles using events
Submit tasks for processing
Task.delegate(event_name)dispatches the task to theRolethat owns the matching workflow. The task carries state (init_context,dependencies) across workflow steps, so each action in the chain has access to previous results.
For detailed examples and advanced usage patterns, explore the examples/ directory in the repository.