From Python to Go: rewriting a CrewAI workflow in pure stdlib
DEV Community

From Python to Go: rewriting a CrewAI workflow in pure stdlib

In the CrewAI Python framework you assemble teams of agents that collaborate via LLMs. Itโ€™s a great model when tasks require multiple specialists. But pulling in litellm, langchain, pydantic and friends makes cold starts heavy and deployment a container story. A few months ago I started crewai-go, an idiomatic Go port with zero external dependencies. The whole core package is pure net/http, encoding/json, log/slog and friends. This post walks through a minimal port of the canonical CrewAI โ€œresearch โ†’ writeโ€ example, side-by-side with the Python version. Python (CrewAI) from crewai import Agent, Crew, Process, Task researcher = Agent( role="Senior Researcher", goal="Uncover the best practices in concurrency", backstory="You are a veteran engineer with deep distributed-systems chops.", ) writer = Agent( role="Tech Writer", goal="Write a concise summary", backstory="You turn research into tight prose.", ) research = Task(description="Research Go concurrency best practices", expected_output="Bullet list of 5 best practices", agent=researcher) write = Task(description="Write a 1-paragraph summary from the research", expected_output="A single paragraph", agent=writer) crew = Crew(agents=[researcher, writer], tasks=[research, write], process=Process.sequential) print(crew.kickoff().final) Go (crewai-go) package main import ( "context" "fmt" "github.com/rhgs/crewai-go" "github.com/rhgs/crewai-go/llm/openai" ) func main() { llm := openai.New("gpt-4o-mini") // uses OPENAI_API_KEY researcher := crewai.NewAgent( "Senior Researcher", "Uncover the best practices in concurrency", "You are a veteran engineer with deep distributed-systems chops.", llm, ) writer := crewai.NewAgent( "Tech Writer", "Write a concise summary", "You turn research into tight prose.", llm, ) research := crewai.NewTask( "Research Go concurrency best practices", "Bullet list of 5 best practices", researcher, ) write := crewai.NewTask( "Write a 1-paragraph summary from the research", "A single paragraph", writer, ).WithContext(research) // explicit dependency, like CrewAIโ€™s context crew := crewai.NewCrew([]*crewai.Agent{researcher, writer}, []*crewai.Task{research, write}) out, _ := crew.Kickoff(context.Background(), nil) fmt.Println(out.Final) } - Same surface, different runtime - Same concepts: Agent, Task, Crew, Process. - Sequential, Hierarchical and Staged processes (stages run in sequence; tasks within a stage run concurrently). - Agentic loop (opt-in Plan-Execute-Evaluate-Refine) with an independent evaluator and bounded refinements. - Web search, structured output with JSON Schema repair loop, guardrails, facts & provenance - all of it built on stdlib only. Why port it? - Single binary (GOOS=linux GOARCH=arm64 go build from your laptop). - Millisecond cold start, ~10-20 MB memory footprint. - Thread-safe end-to-end; CI runs go test -race. - ~94% test coverage, hard 90% gate. Try it git clone https://github.com/rhgs/crewai-go cd crewai-go export OPENAI_API_KEY=sk-... go run ./examples/sequential Thereโ€™s also examples/agentic_loop which runs fully offline with a mock LLM - no API key needed. If youโ€™re a Go developer working on LLM orchestration, give it a star, file an issue, or open a PR. The CONTRIBUTING guide is bilingual (English + Brazilian Portuguese) and the PR checklist is short. Repo: https://github.com/rhgs/crewai-go v0.4.0 release: https://github.com/rhgs/crewai-go/releases/tag/v0.4.0 Happy hacking. Top comments (1) Really interesting approach, especially the staged execution model. One thing I'm curious about: go test -race gives you confidence against memory-level data races, but how are you handling semantic races when multiple tasks inside a stage run concurrently?For example, if two agents produce facts or context that later get merged into the next stage, can completion order affect the final prompt/state? Did you make stage outputs immutable and merge them deterministically, or is ordering deliberately part of the orchestration semantics?

Read on DEV Community ↗ ← Back to News

Comments

No comments yet. Start the discussion.