How I Built an AI Software Team with LangGraph, Docker, and Slack
AI coding demos usually end at the impressive part: an agent receives a prompt, writes code, and produces something that almost works.
Then the expensive questions arrive.
Who checks the result? What happens when the agent loops, edits the wrong repo, or confidently ships garbage? And who gets the kill switch?
I built Ghulam to answer those questions.
Ghulam (غلام) comes from Arabic and is often translated as “servant”—a deliberately humble name for software built to do the work, not run the show.
Architecture and configuration accurate as of September 2026.
- Five specialized roles: PM, frontend coding, backend coding, QA, and marketing
- Three are enabled today: PM + the two coding agents
- Slack is the command center; Ghulam HQ is the control panel
- LangGraph runs the workflow with Postgres checkpoints
- ChromaDB keeps memory isolated by project
- Coding happens in persistent sandboxes—Docker locally, Modal when hosted
- Humans approve consequential actions
It is not an autonomous company. That framing is mostly hype.
It is a controlled execution system that delegates repetitive work without delegating judgment.
Meet the team
Each project gets a Slack channel. I invoke a specialist or let the router choose:
/pm break this feature into tasks
/frontend fix the mobile navigation
/backend add retry logic to webhooks
The channel identifies the project. Ghulam loads its repositories, Notion context, active sprint, base branch, and project memory before routing the task.
No ten-paragraph prompt. No "wait, which app are we discussing?"
| Role | Job | Production status |
|---|---|---|
| 📋 PM | Clarify requests, plan work, create Notion tasks | Enabled |
| 🎨 Frontend coder | UI, navigation, client state, mobile and web | Enabled |
| ⚙️ Backend coder | APIs, data, jobs, integrations, infrastructure | Enabled |
| 🧪 QA | Fresh-sandbox testing and acceptance checks | Disabled for now |
| 📣 Marketing | Draft content, announcements, and email | Disabled for now |

The coding agents do not share one giant loop. Each moves through discovery, implementation, and verification. That creates explicit handoffs—and makes failures easier to locate.
Specialization also narrows permissions. One "do everything" agent gets bloated context, conflicting instructions, and dangerous access. Smaller roles create cleaner boundaries.
The human is not a bug
The most important component is the approval boundary.
Ghulam can research, write code, run tests, create a pull request, and draft content without asking me about every keystroke. But it cannot silently cross important boundaries.
Approval is required before:
- accepting a PM task breakdown;
- merging a pull request;
- deploying to Firebase;
- making a Stripe write;
- submitting to an app store;
- publishing content;
- sending email or spending on ads;
- exceeding the configured compute threshold.

The rules are hardcoded and fail closed. If Ghulam receives an unknown action type, it stops rather than guessing whether the action is safe.
Creating a feature branch is cheap and reversible. Deploying to production is not. Treating both actions equally produces either approval fatigue or reckless autonomy.
Write code in a sandbox? Yes. Open a PR? Yes. Push directly to main? Mechanically blocked. Merge or deploy? Human decision.
I can also message a running task, kill it, or take over through Slack and Ghulam HQ.
Autonomy is a dial, not a switch.
Sandboxes beat promises
A system prompt saying "be careful" is not security.
Coding agents work inside a persistent sandbox for the lifetime of a task. The repository, installed packages, edits, and branch survive across discovery, implementation, and verification. When the task ends, the sandbox is removed.
The current controls include:
- memory and CPU limits;
no-new-privilegessecurity mode;- operator kill signals;
- hard blocking of direct pushes to base branches;
- sandbox runtime accounting;
- separate frontend and backend images.
The sandbox currently uses network access because agents need to clone repositories and install packages. Claiming it runs with no network would sound safer—but it would be false.
🔥 Failure mode: the agent loops
Daily spending and call limits, graph iteration thresholds, tool-loop budgets, and a circuit breaker stop runaway execution.
🗂️ Failure mode: it uses the wrong project
The Slack channel resolves to project-scoped repositories, branches, Notion records, credentials, and a separate ChromaDB collection.
🚀 Failure mode: it tries something irreversible
The graph checkpoints and pauses for a Slack approval. No approval, no merge, deploy, send, or publish.
Containing mistakes is more realistic than pretending they will not happen.
Don’t use AI where a script wins
One trap is assigning everything to an LLM because an LLM is available.
Compilation, linting, type checking, tests, branch protection, and deployment builds are deterministic. They belong in tools and CI—not in an agent's opinion.
The division of labor is simple:
- Agents: clarification, planning, implementation, investigation, explanation.
- Software: builds, tests, policies, budgets, and deployment automation.
- Humans: scope, risk, tradeoffs, merges, and release decisions.
The disabled QA role can explore behavior and verify acceptance criteria in a fresh sandbox. It still does not get to vote that a failing test is "probably fine."
What does it cost?
Honest answer: I do not have enough production data to claim a fixed monthly number yet.
Today, the primary agents use DeepSeek v4 Flash. Claude Haiku is an automatic fallback for eligible non-thinking calls. Each role also has a hard daily ceiling:
| Role | Daily LLM ceiling | Daily calls | Sandbox time |
|---|---|---|---|
| PM | $2 | 100 | — |
| Frontend coder | $15 | 200 | 4h |
| Backend coder | $15 | 200 | 4h |
| QA | $2 | 100 | 2h |
| Marketing | $3 | 150 | — |
These are safety caps, not expected spend. QA and marketing are disabled today, so their limits are dormant.
The useful number will be cost per accepted task, not theoretical monthly spend.
Five lessons so far
- Autonomy should be earned. Production currently runs PM plus two coding specialists; QA and marketing can wait.
- Permissions beat personality. Hard boundaries matter more than a clever system prompt.
- Shared state beats agent chatter. Tasks, checkpoints, branches, PRs, and test results beat endless AI meetings.
- Specification becomes the bottleneck. Agents accelerate clear work and amplify vague work.
- Full autonomy is the wrong goal. Remove low-value coordination; preserve human judgment.
The real test
The next step is not adding Agent #6.
It is measuring whether the existing system creates leverage:
- cost per accepted task;
- first-attempt verification pass rate;
- human interventions per workflow;
- request-to-review-ready time;
- failure rate by agent, phase, and tool.
A busy agent swarm is easy to build. A reliable software operation is not.
My goal with Ghulam isn’t more agents. It’s a system I can trust to deliver real work.