AgentWorkshop is a multi-agent orchestration library for Elixir. You create LLM agents, give them roles, and coordinate their work -- all from IEx.
Prerequisites
AgentWorkshop runs CLI-based LLM tools on your behalf. You need at least one installed and authenticated:
- Claude Code --
claudeCLI, authenticated viaclaude login. This is the recommended backend. - OpenAI Codex --
codexCLI, withOPENAI_API_KEYset. Alternative backend.
Agents run these CLIs as your user, with your credentials and permissions.
They can read and write files, run shell commands, and make git commits --
just like you would from the terminal. Use permission_mode and
allowed_tools to control what agents can do.
For source control features (git context injection, worktrees for parallel agents, GitHub integration):
- git -- any recent version
- gh -- GitHub CLI, authenticated via
gh auth login. Needed for the GitHub integration skill.
Installation
Add agent_workshop and a backend to your mix.exs:
def deps do
[
{:agent_workshop, "~> 0.3"},
{:claude_wrapper, "~> 0.4"} # Claude Code CLI backend
]
endOptional dependencies unlock additional features:
# MCP server (expose Workshop as tools for other agents)
{:anubis_mcp, "~> 1.0"},
{:bandit, "~> 1.0"},
{:plug, "~> 1.16"},
# LiveView dashboard (real-time web UI)
{:phoenix, "~> 1.7"},
{:phoenix_live_view, "~> 1.0"},
{:phoenix_html, "~> 4.0"},
# Git context injection
{:git, "~> 0.2"},
# Alternative backend
{:codex_wrapper, "~> 0.2"} # OpenAI Codex CLIFirst session
Start IEx in your project:
$ iex -S mix
Import the Workshop API and configure your backend:
import AgentWorkshop.Workshop
configure(
backend: AgentWorkshop.Backends.Claude,
backend_config: ClaudeWrapper.Config.new(working_dir: "."),
model: "sonnet",
permission_mode: :bypass_permissions,
context: "Elixir project. Run mix test before committing."
)Creating agents
Each agent has a name and a role description that becomes its system prompt:
agent(:impl, "You write clean, well-tested code.", max_turns: 15)
agent(:reviewer, "You review code. Do not modify files.",
model: "opus", allowed_tools: ["Read", "Bash"])Talking to agents
ask/2 sends a message and waits for a response:
ask(:impl, "Implement caching for the user lookup")cast/2 sends a message and returns immediately. The agent works in the
background:
cast(:impl, "Implement the retry logic from issue #12")
status() # see who's working
await(:impl) # wait for the resultPiping results
Chain agents together with pipe/3. The result from one agent is forwarded
to the next:
ask(:impl, "Implement caching")
|> pipe(:reviewer, "Review for edge cases")
|> pipe(:impl, "Address the review feedback")Setup files
Instead of configuring manually each time, put your setup in .workshop.exs:
# .workshop.exs -- auto-loaded on iex -S mix
configure(
backend: AgentWorkshop.Backends.Claude,
backend_config: ClaudeWrapper.Config.new(working_dir: "."),
model: "sonnet",
permission_mode: :bypass_permissions,
context: "My project description.",
mcp: [port: 4222]
)
profile(:coder, "You write clean code.", max_turns: 15)
profile(:reviewer, "Review only.", model: "opus", allowed_tools: ["Read", "Bash"])
agent(:orchestrator, "You coordinate agents.",
workshop_tools: true, model: "sonnet", max_turns: 30)Load a different setup file at any time:
load("examples/board.exs")Checking on things
status() # agent dashboard
info(:impl) # detailed info for one agent
result(:impl) # last response text
cost() # cost breakdown by agent
total_cost() # total spend
history(:impl) # full conversationNext steps
- Orchestration Patterns -- three ways to coordinate agents
- Work Board and Workflows -- structured task management
- MCP Server -- expose Workshop as tools
- Configuration Reference -- all options explained