<div align="center">
  <img
    src="docs/src/public/svg/logo.svg#gh-light-mode-only"
    alt="MASFactory"
    width="620"
  />
  <img
    src="docs/src/public/svg/logo-dark.svg#gh-dark-mode-only"
    alt="MASFactory"
    width="620"
  />
</div>
<p align="center">
    【English   | <a href="README.zh.md">Chinese</a>】
</p>

## 📖 Overview

**MASFactory** is a graph-first Multi-Agent Orchestration framework built for **VibeGraphing** workflows:
start from a natural-language intent to sketch a Graph, iteratively converge the structure with visual preview/editing,
compile it into an executable workflow, and observe runtime states/messages/shared-attributes end-to-end.

Key capabilities:

- **VibeGraphing (intent → graph):** turn “what you want to build” into an initial graph draft, then refine it into a runnable and reusable workflow.
- **Graph contract & composability:** model control flow and field contracts explicitly with `Node/Edge`, and scale with subgraphs, loops, switches, and composite components.
- **Full-path visualization & white-box debugging:** **MASFactory Visualizer** provides topology preview, runtime tracing, and human-in-the-loop interactions.
- **Context protocol (ContextBlock):** unify Memory / RAG / MCP as structured `ContextBlock`s with passive injection and active on-demand retrieval for controllable, auditable context.

## ⚡️Quick Start

### Install MASFactory Environment

#### Install using UV
```bash
# If uv is not installed yet, install uv first
curl -LsSf https://astral.sh/uv/install.sh | sh

# Clone repository
git clone <repository-url>
cd <repo>

# Install dependencies
uv sync

# Install masfactory as python lib
uv pip install -e .
```

#### Install using conda
```bash
# Clone repository
git clone <repository-url>
cd <repo>

# Create conda virtual environment
conda create -n <your-conda-env-name> python=3.10

# Activate virtual environment
conda activate <your-conda-env-name>

# Install dependencies
pip install -r requirements.txt

# Install masfactory as python lib (recommended)
pip install -e .
```

### Preview docs locally (VitePress)

```bash
npm --prefix docs install
npm --prefix docs run docs:dev
```

### Run Multi-Agent Frameworks Reproduced with MASFactory

```bash
# ChatDev
python applications/chatdev/run.py --task "a simple pingpong game" --name "pingpong"

# ChatDev Lite (a lighter workflow example)
python applications/chatdev_lite/workflow/main.py --task "Develop a basic Gomoku game." --name "Gomoku"

# AgentVerse.Tasksolving
python applications/agentverse/tasksolving/main.py --config python_calculator --task "Write a function to calculate the factorial of a number"
```

### Easy Learning

MASFactory keeps the core primitives small (`Node/Edge/Graph`) while remaining scalable. Recommended entry points:

- Docs site (VitePress): `docs/` (English entry: `docs/src/en/start/introduction.md`)
- Agent runtime (Observe/Think/Act): `docs/src/en/guide/agent_runtime.md`
- Context adapters (RAG/Memory/MCP via ContextBlock): `docs/src/en/guide/context_adapters.md`
- Examples: `applications/` (ChatDev, AgentVerse, etc.)
- Graph patterns library: `examples/` (imperative vs declarative, batch runnable)

#### Project Directory Structure

```
.
├── masfactory/               # MASFactory Framework
│   ├── core/                 # Foundation: Node / Edge / Gate / Message
│   ├── components/           # Components (Agents / Graphs / Controls / CustomNode)
│   │   ├── agents/           # Agent, DynamicAgent, SingleAgent
│   │   ├── graphs/           # BaseGraph, Graph, RootGraph, Loop
│   │   └── controls/         # LogicSwitch, AgentSwitch
│   ├── adapters/             # Adapters (Model / Tool / Memory / Retrieval / MCP)
│   │   └── context/          # Context pipeline (ContextBlock / policy / renderer / composer)
│   ├── integrations/         # 3rd-party integrations (MemoryOS / UltraRAG, etc.)
│   ├── utils/                # Utilities (config, hook, Embedding, etc.)
│   ├── resources/            # Resources and static files
│   └── visualizer/           # MASFactory Visualizer runtime integration
├── masfactory-visualizer/    # VSCode extension: MASFactory Visualizer
├── applications/             # Examples and reproductions based on MASFactory
│   ├── chatdev_lite/
│   ├── chatdev/
│   ├── agentverse/
│   ├── camel/
│   └── number_off_demo.py
├── docs/                     # VitePress docs
│   ├── .vitepress/
│   └── src/
│       ├── zh/
│       └── en/
├── examples/                 # Graph patterns (imperative vs declarative)
├── README.md                 # English (default)
├── README.zh.md              # Chinese
├── pyproject.toml
├── requirements.txt
└── uv.lock
```

### Simple Example

This example shows a minimal two-Agent workflow (declarative). For more patterns, see `applications/` and the docs site.

```python
# A minimal runnable example: two Agents collaborating to complete a task (declarative)
from masfactory import RootGraph, Agent, NodeTemplate, OpenAIModel
"""
Diagram:

+----------------------------------------------+
|              RootGraph (demo)                |
|                                              |
|               +-------------+                |
|               |    entry    |                |
|               +-------------+                |
|                   | user_question            |
|                   v                          |
|               +-------------+                |
|               |  analyser   |                |
|               +-------------+                |
|                   | requirements_report      |
|                   v                          |
|               +-------------+                |
|               |    coder    |                |
|               +-------------+                |
|                   | codes                    |
|                   v                          |
|               +-------------+                |
|               |    exit     |                |
|               +-------------+                |
|                                              |
+----------------------------------------------+
"""

# 1) Create model; model parameters can be loaded from config/environment variables
model = OpenAIModel(
    api_key="your api key",
    base_url="your api base url",
    model_name="gpt-4o-mini",
)  

# 2) Reuse a base Agent template
BaseAgent = NodeTemplate(Agent, model=model)

# 3) Declarative graph (requirement analysis -> code writing)
graph = RootGraph(
    name="demo",
    nodes=[
        (
            "analyser",
            BaseAgent(
                instructions=[
                    "You are a software product manager.",
                    "Analyze user requirements and produce a short requirement report.",
                ],
                prompt_template="User request: {user_question}",
            ),
        ),
        (
            "coder",
            BaseAgent(
                instructions=[
                    "You are a senior software engineer.",
                    "Write runnable Python code based on the requirement report.",
                ],
                prompt_template="Requirement report: {requirements_report}",
            ),
        ),
    ],
    edges=[
        ("entry", "analyser", {"user_question": "User request"}),
        ("analyser", "coder", {"requirements_report": "Requirement analysis report"}),
        ("coder", "exit", {"codes": "Program code"}),
    ],
)

# 4) Build and run
graph.build()
output, _attrs = graph.invoke({"user_question": "Write a Python function that adds two numbers"})
print(output)  # => {"codes": "..."}
```

## 🔧Overall Architecture

MASFactory has 3 layers: core engine, component layer, and adapter layer, unified around the `Node/Edge` graph abstraction for control flow and data flow.

### Core Components (Core)
- Node: Abstract computational units on the Graph, with Graphs, Agents, control logic, etc. all being derived classes of Node.
- Edge: Connects two nodes, used for process control and automatic message forwarding.
- Message: Unified message parsing and distribution mechanism.

### Functional Components (Components):

#### Top-level Components:

Top-level components refer to objects that can be directly instantiated and run independently by users. They are at the outermost layer, do not belong to any `Graph`, and will not serve as `Node` or subgraph of other `Graph`.
MASFactory provides two types of top-level components: `SingleAgent` and `RootGraph`.

- **RootGraph:** Top-level executable workflow container. Can be directly instantiated as a "canvas" to host nodes and edges, organize the overall DAG, and handle one-time execution and result output. Main methods:
    - **`create_node`**(cls: `Node`, *args, **kwargs) -> `Node`: Create a node on `RootGraph` (such as `Agent`, `DynamicAgent`, `AgentSwitch`, `LogicSwitch`, `Graph`, `Loop`, `CustomNode`, etc.). cls must be a `Node` subclass (prohibits `SingleAgent` and `RootGraph` as in-graph nodes). Other parameters are passed as-is to the corresponding constructor, returning the node instance.
    - **`create_edge`**(sender: `Node`, receiver: `Node`, keys: dict | None = None) -> `Edge`: Create a directed edge between two nodes; `keys` define fields to be passed and their natural language descriptions.
    - **`build`**() -> None: Recursively build `RootGraph` and its subgraphs/nodes and complete consistency checks; must be executed before calling `invoke`.
    - **`invoke`**(input: dict, attributes: dict | None = None) -> `(dict, dict)`: Start workflow execution; returns `(output, attributes_snapshot)`.

- **SingleAgent:** Lightweight agent detached from graphs for single-step/linear tasks.
    - **`__init__`**(name: str, model: Model adapter, instructions: str | list[str], prompt_template: str | list[str] | None = None, ...)
    - **`invoke`**(input: dict) -> dict: Takes structured dict input and returns structured dict output.
    - Use cases: Quick Q&A, simple tool calls, scripted batch processing, and other tasks that don't require complete workflow orchestration.

#### In-Graph Components
In-graph components are created by `Graph` instances through *`create_node`*, serving as computational nodes in workflows; then connected through *`create_edge`* to form DAG.

- `Graph`: Subworkflow node, reusable and nestable.
    - Features: Built-in `Entry`/`Exit`, serves as "stage" hosting multiple nodes; inherits `BaseGraph`'s node/edge management and consistency validation.
    - Related methods:
    - **`edge_from_entry`**(receiver, keys: dict | None = None)
    - **`edge_to_exit`**(sender, keys: dict | None = None)
    - Use case: Divide complex processes into several sub-stages for reuse and debugging.
    - `RootGraph` is a derived class of `Graph`, with all methods of `Graph`.

- `Loop`: Loop subgraph, encapsulating iteration control and optional LLM termination judgment.
    - Parameters: `name`, `max_iterations`, `model`(optional), `terminate_condition_prompt`(optional), `pull_keys`/`push_keys`
    - Internal: `Controller` controls iteration and termination; `TerminateNode` supports early exit within loop body
    - Related methods:
    - **`edge_from_controller`**(receiver, keys[, ...]): Start each iteration from controller
    - **`edge_to_controller`**(sender, keys[, ...]): Feed intermediate results back to controller to form next round input
    - **`edge_to_terminate_node`**(sender, keys[, ...]): Trigger forced termination within loop body (like break)
    - Termination conditions: Reach `max_iterations` or determined by LLM to meet `terminate_condition_prompt`

- Agents: Agent nodes.
    - `Agent`: Standard agent. Parameters include `name`, `model`, `instructions`, `prompt_template`?, `tools`?, `memories`?, `pull_keys`?, `push_keys`?, `model_settings`?, `role_name`?
    - `DynamicAgent`: When incoming edge message contains *`instruction_key`* (default value is "instructions"), it will dynamically override `Agent`'s *`instructions`*, with other behaviors identical to `Agent`.
    - Features: Core nodes of MASFactory; can inject memory/retrieval context; call tools and RAG, support different model APIs.

- Controls: Routing and control flow nodes.
    - `LogicSwitch`: Conditional routing based on callback functions; use *`condition_binding`*(callback, out_edge) to bind routing conditions.
    - `AgentSwitch`: Semantic routing based on LLM; use *`condition_binding`*(prompt, out_edge) to bind routing semantics.

- `CustomNode`: Lightweight node with custom forward logic through callback functions, convenient for integrating external computation/rules; supports setting logic during initialization or subsequently through *`set_forward`*.

- Unified Constraints (provided by `BaseGraph`):
    - Loop check: Except for legal loops formed by `Loop`'s `Controller`, other loops will be judged as errors.
    - Duplicate edge check: Duplicate edges with same `sender` → `receiver` will be judged as errors.
    - Key conflict check: Duplicate `keys` (including nested) of incoming edges to the same receiving node will be judged as errors.
    - Cannot create `SingleAgent` and `RootGraph` objects through *`create_node`* interface.

### Extension Adaptation Interfaces (Adapters)

The adaptation layer provides unified interfaces for models, tools, memory, and retrieval, ensuring different implementations are pluggable and composable.

#### Model
- Interface: invoke(messages, tools, settings) -> dict, returns CONTENT or TOOL_CALL.
- Implementations: OpenAIModel / AnthropicModel / GeminiModel; automatically adapts message and tool declaration formats of various providers, supports common generation parameters like temperature, max_tokens, top_p, stop, etc.

#### ToolAdapter
- Interface: details provides JSON Schema description of functions; call(name, arguments) executes tools.
- Purpose: Works with Agent to complete the closed loop of "model initiates tool call → execution → return results".

#### Context Adapters (RAG / Memory / MCP)

MASFactory models “LLM-visible context” as structured `ContextBlock`s (driven by `ContextQuery`) and injects them
into the `CONTEXT` field during the Agent Observe phase.

- **Memory (writable):** `insert/update/delete/reset` + `get_blocks(ContextQuery) -> list[ContextBlock]`
  - `HistoryMemory` keeps chat history (carried as messages, not emitted as ContextBlocks)
  - `VectorMemory` stores semantic memory and emits ContextBlocks by similarity
- **Retrieval (read-only RAG):** `get_blocks(ContextQuery) -> list[ContextBlock]`
- **MCP:** map external tool results into ContextBlocks via `MCP(name, call=...)`

Two modes are supported:

- **passive**: auto-injection (default)
- **active**: on-demand retrieval exposed to the model as a tool (`retrieve_context`)

See: `docs/src/en/guide/context_adapters.md` and `docs/src/en/guide/agent_runtime.md`.
