Search

Friday, September 4, 2026

Build a Six-Role AI Software Company by Forking Kimi Code: Multi-Agent SDLC on NVIDIA NIM

Part 5 of the AI Agents series. A six-role software development company — CEO, CPO, CTO, programmer, reviewer, tester — running as native subagents inside a downstream fork of the Kimi Code CLI, powered by free NVIDIA NIM (Nemotron) models, verified on six platforms, and shipping a browser-playable Snakes and Ladders arena.

What this post covers:

  • How to build a multi-agent AI software development team that runs an end-to-end SDLC (inception, blueprint, code, review, test) inside a single coding CLI session.
  • Why forking a production coding CLI (Kimi Code) is a better fit than assembling a separate multi-agent framework (ChatDev, AutoGen, CrewAI) for real-world software delivery.
  • How to make an OpenAI-compatible NVIDIA NIM (Nemotron 3 Ultra 550B, Nemotron 3 Super 120B) endpoint work with a client that assumes Kimi/Anthropic API conventions.
  • A step-by-step install of pre-built binaries on Linux (x64 / ARM64), macOS (Intel / Apple Silicon), and Windows (x64 / ARM64).
  • Honest engineering post-mortems: the WaitFor timeout saga, a GitHub Actions YAML parse bisect, and provider-compatibility gotchas for OpenAI-compatible gateways.
  • A live browser deliverable — a four-player Indian Snakes & Ladders arena — produced end-to-end by the agent team.
Six subagents (ceo, explore, cto, programmer, reviewer, tester) active in a single kimi session on Nemotron 3 Super 120B via NVIDIA NIM, closing out a bad-regressions report against a snakes-and-ladders workspace. Sixty-two minutes in; four subagents already checkpointed and closed, tester still running the verification suite across 153 tool calls.

Six subagents on Nemotron 3 Super 120B via NVIDIA NIM, in one kimi session, closing out a bad-regressions report against a Snakes and Ladders workspace. Sixty-two minutes in; the tester is still running the verification suite across 153 tool calls.

For four posts now this blog has been running someone else's virtual software company — ChatDev 2.0, wired up to free NVIDIA NIM models, and put through progressively harder assignments: a smoke test on Linux, a live AI news debate wall, a cross-platform Ludo game, and finally a public GitHub release stress-tested on eleven runners. The framework held up. Along the way it also demonstrated, in Part 3, that a green build and a passing test suite can quietly ship a completely broken headline feature; and, in Part 4, that "it works on my machine" reliably hides four defects until the code lands on a machine that was not the author's.

This post moves the company one layer down. Instead of using someone else's multi-agent AI framework and someone else's models, SANYALnet Labs now owns the coding harness itself. The virtual software company is no longer a Python process orchestrated from outside; it lives inside a downstream fork of a production AI coding CLI, as six bindable subagents — autonomous coding agents that share a single session, a single model, and a single conversation transcript. This is agentic SDLC done as one continuous transcript, not a message bus between processes.

The framework is a fork of Moonshot AI's kimi-code. The company is called SANYALnet Labs, inspired directly by ChatDev's role structure but rebuilt around the CLI's native subagent primitive. The deliverable it produced — covered in full in the next post — is a browser-playable Snakes and Ladders game.

The company, before the fork

The six roles are deliberately close to ChatDev's, so nothing here needs to be re-explained if you have followed the earlier posts:

  • CEO — active decision-maker on requirements, scope, and final sign-off.
  • CPO — user experience, interface, and workflow design.
  • CTO — architecture, technology stack, framework patterns.
  • Programmer — clean production code, dependency management, iterative fixes.
  • Reviewer — a rigorous audit persona that flags logic errors, concurrency bugs, and structural anti-patterns without touching source files itself.
  • Tester — dynamic and black-box verification, edge-case hunting, and a formal QA certificate at the end.

What is new is how they cooperate. There is one master directive — the SDLC Multi-Agent Project Directive — that binds all six into a five-phase workflow: an inception audit run by the CEO and CPO, an architectural blueprint from the CTO, an implementation pass by the programmer, a review loop, and a QA certification. And then, the non-negotiable rule that turned out to matter more than any of the others:

Phase 1 runs automatically. Every subsequent phase is gated on an explicit operator instruction. If the operator's directive is ambiguous, the CEO must ask one clarifying question and HALT again — never guess intent.

That halt is the entire ethos of the fork. The framework will not autonomously proceed past the initial audit. It reads the current project folder — README, agent files, package manifests, CI workflows, recent commit history — and hands the operator a Project Status Briefing: project identity, tech stack, repository shape, current state with file-and-line citations, open questions the audit could not resolve, and a bulleted menu of ready-to-run tasks framed as candidate PRDs rather than commitments. Then it stops and asks what to do.

After the pattern in Part 3's Ludo game, where the built game passed its own test suite while every AI player silently defaulted to local fallback, an explicit human gate before Phase 2 stopped feeling like friction and started feeling like the point.

Phase-to-phase, in a single session

Because all six personas live inside one kimi session on the same model, phase handoffs are not an out-of-band coordination problem. They are just the next sentence in the transcript. The programmer signs off; the top-level assistant observes what happened; the reviewer picks up the diff.

Terminal showing the Programmer subagent completed on Nemotron 3 Super 120B via NVIDIA NIM after 4m 11s and 30 tool calls, with the message 'All moveId commits are preserved as required. The file is ready for reviewer and tester sign-off.' immediately followed by the top-level assistant deciding 'Now we have the programmer's work. Next, we need the reviewer to audit the programmer's diff' and the Reviewer subagent starting up.

Programmer signs off, reviewer picks up. Same session, same model, no proxy.

Terminal showing the Reviewer subagent completed on Nemotron 3 Super 120B via NVIDIA NIM after 1m 20s and 2 tool calls, immediately followed by the top-level assistant deciding 'Now we need the tester to perform dynamic proof and run verification scripts' and the Tester subagent starting up with 'We'll also look at the package.json to see how to start the server.'

Reviewer signs off, tester picks up. The whole SDLC is one continuous transcript.

The two screenshots above are consecutive moments in a single session that was fixing a real regression in the Snakes and Ladders build. Notice what is not in either frame: no orchestration harness, no queue, no inter-process message bus, no separate model per role. Just the top-level assistant reasoning about which persona to invoke next, and the persona doing its job with the tools it has.

Owning the harness

The company setup lives in sanyalnet-lab/ inside the fork: six persona Markdown files under agents/, the SDLC directive, an install.sh that symlinks everything into place on a lab box, a config.toml template, and two very large review-workflow playbooks — one written for DeepSeek V4 Pro and one written for Nemotron 3 Ultra 550B A55B — that describe, in several thousand lines each, how to run a full company-scale code review against a checkout.

The fork itself sits ahead of upstream by a few dozen commits. Almost none of them are cosmetic. The interesting ones fall into four honest categories.

Provider compatibility: teaching the CLI to speak NIM

Upstream kimi-code targets the Kimi API. Pointing it at a strict OpenAI-compatible gateway — NVIDIA NIM in particular — surfaces small but fatal incompatibilities. The most visible one was prompt_cache_key: Kimi's client sends it by default, NIM's strict endpoint rejects requests that carry unknown top-level fields, and every single call fails until the key is opted out on providers that do not support it. The fix was a small provider-flag change plus documentation for the fork-only environment variable that governs it.

The other addition in the same theme was a one-second minimum interval between model-driven outbound fetches. This is exactly the failure mode Part 3 described when Nemotron 3 Ultra was rate-limited to failure on the free tier: without a floor, an eager agent turns a burst of legitimate tool calls into a 429 storm and the whole session goes red. A single second of enforced spacing turned that from a session-killing problem into a barely-noticeable pause.

There is also a deliberate feature removal: auto-update is disabled unconditionally in the fork, with a documented opt-in switch for anyone who wants the upstream behaviour back. A lab box should be deterministic; a coding harness that mutates itself between runs is a debugging nightmare and, worse, a source of the kind of "worked yesterday" ghost that Part 4's eleven-runner sweep would eventually catch anyway.

The WaitFor saga: a green test can hide a schema token

The single richest failure story in the fork is the WaitFor tool's timeout cap. The upstream default is ten minutes, which is fine for interactive coding but catastrophic for a five-phase SDLC where the programmer subagent will happily disappear into a compile-run-fix loop for longer than that. The requirement was to raise it.

The first attempt raised it to seven days. Tests went red. The revert landed with a note documenting exactly why the change had been unsafe, which is already better than most retracted commits get.

The second attempt tried to raise it to seven days without changing the schema description tokens — because the failing tests turned out to be asserting against the human-readable description string, not the numeric cap. That worked, but 604,800 seconds proved to be more headroom than anyone actually wanted and gave up too much of the schema's self-documentation.

The third attempt settled on 999 seconds — sixteen minutes and forty seconds — a number chosen to fit the schema's existing three-digit formatting and to comfortably outrun any single phase without being absurd. This one broke a different set of tests: snapshot tests that had hard-coded the literal string "10 minutes" as expected output. So the fourth attempt landed the 999-second cap together with a new regen-snapshots workflow, which itself needed a follow-up fix because the workflow was invoking the test runner through a wrapper that swallowed the --update flag before it reached the actual snapshot regenerator.

The final commit in the sequence — the one that finally shipped — regenerated all the affected snapshots against the new cap and updated the release notes to surface both the 999-second cap and a related fix that made 404 responses retryable in the OpenAI-compatible client.

Two reverts, four commits, one follow-up workflow, one workflow bugfix, one snapshot regeneration pass, and a documentation update — to move a number from 600 to 999. Every one of those commits is in the log. In the spirit of Part 3's "a green build and a passing suite can conceal a headline feature that is silently, completely broken", this one earns a companion: a passing snapshot test suite can pin a schema description string in place hard enough to block a feature bump, and there is no external symptom until you try to raise it.

The YAML bisect: reducing a workflow to its parse blocker

The E2E acceptance workflow — the one that runs the SANYALnet company end to end on every push against a smoke workspace — went through a debug chain that will be familiar to anyone who read Part 4. The workflow would not parse. The commits, in order: reduce the workflow to its bare minimum to isolate the parse blocker; add back the inputs block only; add back a two-job gate with a needs pattern; add back the full matrix with a runner_group custom key; and, finally, replace the multi-line quoted expected string that turned out to be the actual blocker with a bash array, and env-ify every input read for good measure. Along the way: dropping parentheses from a workflow name that were breaking the parser, simplifying a case+sed chain that GitHub Actions' YAML loader interpreted differently from local yq, defaulting input expressions so on-push validation would stop failing, and — the payoff commit — passing timeout_minutes as a string rather than a number to unblock parsing entirely.

Same method as the Ludo game's build-vs-play model split in Part 3, and same method as Part 4's self-hosted runner shakedown: shrink the failing thing to nothing, add pieces back until it breaks, and let the log tell the story afterwards. It is not glamorous but it is reliable, and the resulting workflow — which now runs the company against a Snakes and Ladders smoke workspace on every runner in the matrix on every push — is worth the debug chain that got it there.

The filesystem-driven autoload, and the operator loop

Two small ergonomic changes did more for the day-to-day feel of the company than any of the larger features. The first is KIMI_INITIAL_PROMPT_FILE, an environment variable that tells the fork to autoload a Markdown file into the editor at session start. The lab box's install script symlinks the SDLC directive into that path, so launching kimi in the workspace of any project puts the directive on screen with the cursor at the bottom, ready for the operator to hit Enter. There is no manual copy-paste of a prompt, no menu, no per-project setup: the moment the session opens, the company is one keystroke away from starting Phase 1.

The second is the default-model change. After the sweep in Part 3 that tested five free NVIDIA models against a complex build task, and after some further comparison work on more modest tasks, the company default was set to Nemotron 3 Ultra 550B A55B — which is what a fresh install now runs on unless the operator changes it. The point is not that this is the best model for every task (Part 3's build required a paid DeepSeek V4 Pro), but that it is a reasonable, capable, reliably available free-tier default for a company that spends most of its time doing audits, reviews, and incremental implementation work rather than orchestrating a from-scratch cross-platform desktop build.

Try it yourself: six-platform install (step-by-step)

The fork ships pre-built binaries for every platform the underlying CLI supports — linux-x64, linux-arm64, darwin-x64 (Intel Mac), darwin-arm64 (Apple Silicon), win32-x64, and win32-arm64 — under the kimi-code-sanyalnet-cli-vX.Y.Z release tag. A GitHub Actions smoke workflow deploys the company via install.sh onto all six runners on every push to main, so if a release is out, the install path has been verified end-to-end on your operating system and CPU architecture within the last few hours.

Setup is two steps. The first installs the fork binary; the second installs the six-role software company on top of it.

1. Fork binary. Grab the appropriate zip from the latest fork release, unzip, put kimi on your PATH. On macOS you must clear the quarantine flag before first launch (xattr -dr com.apple.quarantine /path/to/kimi).

2. Company setup. Clone the fork and run the installer:

git clone https://github.com/tuklusan/kimi-code.git
cd kimi-code/sanyalnet-lab
./bin/install.sh --autoload

The installer is idempotent. It symlinks the six agent personas, the SDLC directive, and both review-workflow playbooks into ~/.kimi-code/; wires the initial-prompt autoload into your ~/.bashrc; and prompts (once, silently) for your NVIDIA NIM API key to seed a fresh ~/.kimi-code/config.toml from the redacted template. If a config already exists, the installer leaves it alone — re-run any time after a git pull to refresh the persona symlinks without touching your keys.

Launch kimi in the workspace of any project. The SDLC directive is pre-loaded in the editor; press Enter, and Phase 1 begins the forensic audit. The company then halts and waits for your instruction.

What the company actually built

The hero image at the top of this post is a real session, not a mockup. The CEO subagent is sixty-two minutes in, driving an internal all-hands to close a bad-regression report reading "pieces not moving, ladders shaped like ladders, snakes look wrong." Four other subagents — the explore agent, the CTO, the programmer, and the reviewer — have already checkpointed their phases and closed out. The tester has been running a Node-based verification suite for forty-three minutes across a hundred and fifty-three tool calls and is about to sign off. All six subagents are on the same Nemotron 3 Super 120B model, through NVIDIA NIM, in one kimi session, with no proxy in front. The workspace under audit is a snakes-and-ladders project.

Full recorded session of the six-role software development company delivering Snakes and Ladders end to end (rev 1.0.0, ~20 MB). If the inline player does not load, download the raw MP4 directly. An earlier rev 0.0.3 capture is kept as a historical artefact.

The finished product is live and playable in any browser right now: tuklusan.github.io/snakes-and-ladders-arena — a four-player Indian Snakes & Ladders arena with procedural boards, SVG-rendered snakes and ladders, smooth animation, twelve audio cues, and kiosk-ready auto-play. Zero build step, zero server: the whole thing is static files served straight off GitHub Pages. Source is at github.com/tuklusan/snakes-and-ladders-arena.

The full story of what that Snakes and Ladders project became — the requirements, the CTO's blueprint, the programmer's implementation loop, the reviewer's audit passes, the tester's certificate, and how the finished browser-playable game came together — is the next post in this series, at Build Snakes and Ladders as a Web Game with AI Agents.

The production run: what the fork actually carried

Seven sessions, five and a half days, three thousand three hundred and forty-six LLM turns. That is what it took the company to carry Snakes & Ladders from an early beta-0.0.4 baseline to a mobile-verified release 1.0.1 — and what makes it a fair stress test of the harness rather than a toy demo. Every fork provision the sections above describe was pulled out of that fire; here is how, in a paragraph per session.

Session 1 (Aug 27, ~6 hours, Nemotron 3 Super 120B, fifty-seven subagents). The first CEO run failed exactly the way Part 3 warned it would: the CEO wrote the code solo and the reviewer signed off against headless snapshots that the real kiosk contradicted. The operator instituted a hard rule — "the reviewer must VISUALLY inspect the ACTUAL rendered board on the REAL kiosk across an ENTIRE game" — that has ridden in every brief since.

Session 2 (Aug 28, ~2 hours). The company switched to Nemotron 3 Ultra 550B A55B — the fork's new default, flipped mid-build in the commit feat(sanyalnet): default the company to Nemotron 3 Ultra 550B A55B. First session ending cleanly with lastTurnReason=completed. beta-0.0.4 shipped.

Session 3 (Aug 29–31, fifty-one operator turns — the longest). Speckled snakes, halved tile-number font, snake-slide animation restored, beta-0.1.0 tagged. Then the operator handed the CEO the DeepSeek V4 Pro review-workflow playbook — the exact 4,515-line file that ships in sanyalnet-lab/review-workflows/ — in first production use. The review surfaced twenty-eight defects, catalogued as DEF-0001DEF-0033.

Session 4 (Aug 31, eight turns). Small tagging session with one load-bearing sentence. Operator turn 5, in full: "Please consider 404 status code from model as retryable, and continue." That single request became the fork commit feat(sanyalnet): 404 retryable, WaitFor cap 7d, ship review workflows. The blog's earlier "WaitFor saga" and its companion "make 404 retryable" fix trace directly back to this turn.

Session 5 (Sep 1–2, twenty-one turns). The operator caught that the twenty-eight DeepSeek defects had been force-closed rather than repaired, and made the CEO actually fix them in priority order — DOM XSS via innerHTML, unbound event handlers, undefined properties, layout overflows, a dead speckle filter that was defined but never applied. Then the second review workflow landed: nvidia-nim-nemotron3-ultra-software-company-review-workflow-final, the 4,996-line Nemotron playbook, run against the same codebase as an independent adjudicator.

Sessions 6 and 7 (Sep 2–3, iOS Web Audio saga). The iPhone revealed that sounds through HTMLAudioElement trail their event by a perceptible lag on WebKit. Five surgical rounds under a hard scope lock — "touch ONLY the audio load/play/unlock code in gameView.js" — hunted the failure through an asset-tally double-count, a corrupt step.mp3 WebKit refused to decode, a CDN cache-busting miss, and finally an InvalidStateError throw from audio.currentTime = 0 on iOS readyState 0 that killed the entire start handler. Session 6 ended with an operator halt for repository recovery; session 7 rebuilt both fixes correctly on a clean baseline, added a showStartButton() guard for a follow-up race, and closed with a docs-only 1.0.1 consistency pass. lastTurnReason=completed. Accepted on iPhone 12, iPhone 15 Pro Max, and desktop.

Every fork capability the earlier sections describe — the operator-halt gate, the Nemotron 3 Ultra default, the two review-workflow playbooks, 404-retryable, the WaitFor cap headroom, the initial-prompt autoload, the deterministic auto-update-off — was either exercised or brought into existence by this five-and-a-half-day run. The full build story of the game itself — requirements, blueprint, review passes, QA certification, and the finished browser deliverable — is the next post in this series.

Lessons from owning the harness

Three carry over from the earlier posts, sharpened by the experience of running the company from inside the CLI rather than beside it.

A human gate is a feature, not friction. After Part 3's silently broken Ludo game, hard-coding a HALT into the SDLC directive between the automatic audit and every downstream phase turned out to be the single highest-leverage design decision in the fork. The company reads your project, tells you what it sees, offers a menu, and stops. Nothing gets built until the operator says what to build.

Provider compatibility is not the same as model capability. A capable model behind a strict OpenAI-compatible gateway will die on a single unrecognised field just as thoroughly as an incapable model. Owning the harness meant owning the client, which meant the prompt_cache_key opt-out and the outbound-fetch throttle could just be fixed, once, in the right place.

Green tests protect the past, not the future. Part 3 warned that a passing suite can hide a broken feature. The WaitFor saga in this fork adds that a passing suite can also freeze a schema in place: the tests were doing their job perfectly, asserting that the description string had not changed, and the change was legitimate. The lesson is not that snapshot tests are bad — they are excellent — but that raising a limit is a two-part job, and the second part is deleting the old snapshots and regenerating them under the new limit, deliberately, as a commit of its own.

Frequently asked questions

Can you actually run a full AI software development company on free models?
Yes, for the majority of tasks. The company defaults to Nemotron 3 Ultra 550B A55B on the NVIDIA NIM free tier, and the screenshots in this post are a real session on Nemotron 3 Super 120B, also free. The one caveat is heavyweight from-scratch cross-platform builds — the Ludo game in Part 3 needed paid DeepSeek V4 Pro to finish, at a total cost of about $1.13. For audits, reviews, incremental implementation, and browser-scale web projects, free-tier Nemotron is enough.

How is this different from ChatDev, AutoGen, CrewAI, or MetaGPT?
Those are stand-alone Python multi-agent frameworks that orchestrate LLM calls from outside your editor. SANYALnet Labs runs inside a production coding CLI (a fork of Kimi Code) as native subagents that share one session, one conversation transcript, one workspace, and the same tool surface (file system, shell, git, MCP servers) that a solo developer would use. The result feels like six colleagues working in the same terminal, not six processes coordinating over a queue.

Do I need a paid API key to try it?
No. A free NVIDIA NIM key from build.nvidia.com is enough for the whole install, the Phase 1 project audit, and most day-to-day company work. Add a DeepSeek key later only if you want to run the DeepSeek V4 Pro adjudicated code-review workflow.

What operating systems and CPU architectures are supported?
Six: Linux x64, Linux ARM64, macOS Intel (x64), macOS Apple Silicon (ARM64), Windows x64, and Windows ARM64. Pre-built binaries for every combination ship under the kimi-code-sanyalnet-cli-vX.Y.Z release tag, and a GitHub Actions smoke workflow verifies the install path on all six on every push to main.

Will it modify my existing codebase without asking?
No. The SDLC directive halts after the automatic Phase 1 audit and refuses to proceed to blueprint, code, review, or test phases without an explicit operator instruction. You get an evidence-backed Project Status Briefing with file-and-line citations, a menu of candidate next steps, and a hard stop — nothing gets written, refactored, or deleted until you approve a scope.

Is this a good fit for solo developers, or only teams?
Solo developers benefit the most, because the company gives one person the leverage of a five-person engineering team — a strategist, an architect, an implementer, a reviewer, and a QA engineer — without the coordination overhead. The operator-halt design means the human stays in the loop on every scope decision, which is exactly what a solo developer wants.

How does it compare to using a single AI coding assistant?
A single assistant conflates roles: the same context that just wrote the code is asked to review it, which produces predictably shallow audits. Splitting the work across six subagents with dedicated persona prompts — each with its own reasoning context and its own definition of "done" — catches classes of defects a monolithic assistant misses, especially concurrency bugs, silent fallbacks (see Part 3), and integration-test coverage gaps.


The AI Agents series so far: