Skip to content

First Code (0 → 1) ​

Goal: write a runnable MASFactory workflow in minutes and understand the essential APIs: RootGraph / Node / Edge / build / invoke.


0) Two concepts to understand first ​

  1. MASFactory uses Python dict as the message carrier. Inputs, node outputs, and edge payloads are all structured as dict. The smallest unit of message exchange is a single field in that dict.
  • Horizontal message passing: nodes exchange payloads through Edge inside the same graph. Edge.keys defines the field contract and routing rule (“which fields flow across this hop”).
  • Vertical message passing: a node exchanges state with its containing graph through attributes (node attributes). pull_keys / push_keys decide which fields are read from / written back to attributes.
  • For details, see: Message Passing.
  1. RootGraph.invoke(...) returns a tuple: (output_dict, attributes_dict). The first item is the final output of horizontal passing; the second item is a snapshot of the graph attributes (vertical state).

Diagram: Horizontal (Edge) + Vertical (attributes) ​

Message overview: horizontal (Edge) + vertical (attributes)

1) Your first Agent workflow ​

We build a simple QA workflow with two agents: one for analysis and one for answering.

Diagram: analyze → answer ​

First Agent workflow: ENTRY → analyze → answer → EXIT
python
from masfactory import RootGraph, Agent, OpenAIModel, NodeTemplate, HistoryMemory, Shared, Factory

model = OpenAIModel(
    api_key="YOUR_API_KEY",
    base_url="YOUR_BASE_URL",
    model_name="gpt-4o-mini",
)

BaseAgent = NodeTemplate(
    Agent,
    model=Shared(model),
    memories=[Factory(lambda: HistoryMemory(top_k=12))],
)

g = RootGraph(
    name="qa_two_stage",
    nodes=[
        ("analyze", BaseAgent(instructions="You are a problem analysis expert.", prompt_template="User question: {query}")),
        ("answer", BaseAgent(instructions="You are a solution expert. Provide the final answer based on the analysis.", prompt_template="Question: {query}\nAnalysis: {analysis}")),
    ],
    edges=[
        ("entry", "analyze", {"query": "User question"}),
        ("analyze", "answer", {"query": "Original question", "analysis": "Analysis result"}),
        ("answer", "exit", {"answer": "Final answer"}),
    ],
)

g.build()
out, _attrs = g.invoke({"query": "I want to learn Python. Where should I start?"})
print(out["answer"])

Read model config from environment variables

MASFactory does not auto-load environment variables. You can wire them in yourself:

python
import os
from masfactory import OpenAIModel

model = OpenAIModel(
    api_key=os.getenv("OPENAI_API_KEY", ""),
    base_url=os.getenv("OPENAI_BASE_URL") or None,
    model_name=os.getenv("OPENAI_MODEL_NAME", "gpt-4o-mini"),
)

Why doesn’t an Agent read attributes by default?

Agent.pull_keys / Agent.push_keys defaults to {}. With this setting, an agent does not read from or write back to graph attributes.
If you want an agent to read from attributes, explicitly set pull_keys to the required fields. If you set pull_keys=None, it will inherit all attributes.

Want reusable capability packs?

If you want to reuse Anthropic-style SKILL.md capability packages across agents, see: Skills.


  • For a systematic understanding of declarative orchestration: read the Development Guide and Examples.
  • For runnable workflows: continue with the Examples section, or check applications/*/README.md in this repository.