Migration Guides¶
How to move from other orchestration frameworks to Bernstein.
From CrewAI¶
Key differences¶
| CrewAI | Bernstein |
|---|---|
| Agents are LLM-based with role prompts | Agents are CLI processes (Claude Code, Codex, etc.) |
| Orchestration via LLM reasoning | Orchestration via deterministic code |
| State in memory | State in files (.sdd/) |
| Long-lived agent conversations | Short-lived agents (1-3 tasks, then exit) |
| Python API for defining crews | YAML plan files + CLI |
| Custom tools via Python functions | Agents use their own built-in tools |
Migration steps¶
1. Map your Crew to a plan file
CrewAI:
from crewai import Agent, Task, Crew
researcher = Agent(role="Researcher", goal="Research the topic")
writer = Agent(role="Writer", goal="Write the content")
research_task = Task(description="Research AI trends", agent=researcher)
write_task = Task(description="Write a blog post", agent=writer)
crew = Crew(agents=[researcher, writer], tasks=[research_task, write_task])
crew.kickoff()
Bernstein:
# plans/blog-post.yaml
name: "Blog post pipeline"
stages:
- name: research
steps:
- goal: "Research current AI trends and create notes in docs/research-notes.md"
role: researcher
priority: 1
scope: ["docs/"]
complexity: medium
- name: writing
depends_on: [research]
steps:
- goal: "Write a blog post based on docs/research-notes.md, output to docs/blog-post.md"
role: docs
priority: 2
scope: ["docs/"]
complexity: medium
2. Replace custom tools with file-based communication
CrewAI agents share data through tool calls and memory. Bernstein agents share data through files in the repository.
CrewAI:
Bernstein approach: agents read and write files. If agent A produces output in docs/research.md, agent B reads it from disk.
3. Replace delegation with stage dependencies
CrewAI:
Bernstein:
stages:
- name: plan
steps:
- goal: "Break down the feature into subtasks and write them to docs/subtasks.md"
role: manager
- name: execute
depends_on: [plan]
steps:
- goal: "Implement subtask 1"
role: backend
- goal: "Implement subtask 2"
role: backend
4. Replace memory with .sdd/
CrewAI uses short-term (conversation) and long-term (vector store) memory. Bernstein uses: - .sdd/backlog/ for task state - .sdd/memory/ for cross-run knowledge - .sdd/bulletin/ for inter-agent messages within a run - Repository files for agent output
From LangGraph¶
Key differences¶
| LangGraph | Bernstein |
|---|---|
| Graph-based agent workflows | Stage-based task orchestration |
| LLM decides control flow | Deterministic control flow |
| Checkpointing via state snapshots | WAL + file-based state |
| Python code defines graph | YAML plan files |
| Single process, async nodes | Multi-process, one per agent |
| Custom LLM chains | Standard CLI agents |
Migration steps¶
1. Map graph nodes to plan stages
LangGraph:
from langgraph.graph import StateGraph
graph = StateGraph(State)
graph.add_node("analyze", analyze_code)
graph.add_node("implement", implement_changes)
graph.add_node("test", run_tests)
graph.add_edge("analyze", "implement")
graph.add_edge("implement", "test")
graph.add_conditional_edges("test", check_results, {"pass": END, "fail": "implement"})
Bernstein:
stages:
- name: analyze
steps:
- goal: "Analyze the codebase and write findings to docs/analysis.md"
role: architect
- name: implement
depends_on: [analyze]
steps:
- goal: "Implement changes based on docs/analysis.md"
role: backend
- name: test
depends_on: [implement]
steps:
- goal: "Run tests and fix any failures"
role: qa
2. Replace conditional edges with quality gates
LangGraph conditional routing is done by LLM or code. Bernstein uses quality gates:
quality_gates:
after_implement:
- type: test
command: "pytest tests/ -x"
- type: lint
command: "ruff check src/"
Failed quality gates automatically trigger retries.
3. Replace state checkpoints with WAL
LangGraph:
Bernstein automatically maintains a WAL in .sdd/runtime/wal/. Recovery is automatic on restart.
4. Replace tool definitions with agent capabilities
LangGraph nodes often call custom tools. Bernstein agents (Claude Code, Codex, etc.) come with built-in tools for file editing, terminal commands, and web search. No custom tool definitions needed.
From AutoGen¶
Key differences¶
| AutoGen | Bernstein |
|---|---|
| Multi-agent conversations | File-based task dispatch |
| GroupChat for coordination | Orchestrator tick loop + bulletin board |
| LLM-driven turn-taking | Priority-based queue |
| In-memory state | File-based .sdd/ state |
| Python API | YAML plans + CLI |
| Agents are chat participants | Agents are isolated processes |
Migration steps¶
1. Replace GroupChat with plan files
AutoGen:
from autogen import AssistantAgent, UserProxyAgent, GroupChat, GroupChatManager
coder = AssistantAgent("coder", llm_config=config)
reviewer = AssistantAgent("reviewer", llm_config=config)
chat = GroupChat(agents=[coder, reviewer], messages=[])
manager = GroupChatManager(groupchat=chat)
user.initiate_chat(manager, message="Build a REST API")
Bernstein:
stages:
- name: code
steps:
- goal: "Build a REST API for the user service"
role: backend
- name: review
depends_on: [code]
steps:
- goal: "Review the REST API implementation and fix issues"
role: reviewer
2. Replace agent conversations with file I/O
AutoGen agents talk to each other in a chat thread. Bernstein agents communicate through: - Files in the repo: Agent A writes code, Agent B reads and reviews it - Bulletin board: Post cross-agent findings via the /bulletin API endpoint - Task metadata: Progress reports attached to tasks
3. Replace UserProxyAgent with the orchestrator
AutoGen's UserProxyAgent acts as a human stand-in. In Bernstein, the orchestrator fills this role deterministically -- no LLM needed for coordination.
4. Replace function calling with CLI agents
AutoGen:
@user.register_for_execution()
@coder.register_for_llm(description="Run tests")
def run_tests(test_file: str) -> str:
return subprocess.run(["pytest", test_file], capture_output=True).stdout
Bernstein agents have built-in terminal access and can run any command directly.
General migration tips¶
-
Start with a simple plan. Convert your simplest workflow first and verify it works before tackling complex multi-stage pipelines.
-
Use file-based communication. Instead of in-memory agent message passing, have agents write intermediate results to files that downstream agents read.
-
Rely on the orchestrator. Do not try to replicate LLM-based coordination. Bernstein's deterministic orchestrator handles task dispatch, retries, and resource management.
-
Use existing CLI agents. Do not rewrite custom tools. Claude Code, Codex, and other agents already know how to edit files, run tests, and use git.
-
Use quality gates instead of LLM-based evaluation. Instead of asking an LLM "is this good?", run concrete checks: tests pass, lint clean, type check clean.