I built my own AI startup because I got tired of AI being too independent
I built my own AI startup because I got tired of AI being too independent
Preface, or why I sat down to write this at all
Like every developer, I use AI (LLMs, for those who like precision) for work. It all started in 2024, when vibe coding was just emerging. First we manually copy-pasted code from the browser. Then Cursor and Copilot came and flipped the IT industry. Now there's a glut of vibe coding tools: Claude Code, Codex, Cursor, Lovable, Bolt, Windsurf, OpenCode, Goose... And a dozen more.
And all of them share the same problem: over-autonomy.
You give a task "write a simple HTTP server" and 15 minutes later AI spits out a microservice architecture with Redis, PostgreSQL, Docker Compose, three endpoints, JWT auth, and CI/CD. You say "fix a bug in one function" and it refactors half the project, adds new dependencies, and breaks what was working. You look away for a minute — and it's already pushed a branch with 40 changed files, half of which have nothing to do with the task.
And the worst part — this happens exactly when you stop understanding what's going on. When the task is complex, you trust the AI, and it flies off into its own weeds. And you sit there wondering — is this what I asked for, or is it making stuff up again?
There's even a meme about developers in 2026: they walk around with their laptop slightly open so Claude Code doesn't stop. AND THIS, FOR FUCK'S SAKE, IS A REAL PROBLEM THAT NO ONE IS PAYING ATTENTION TO.
Why should I have to create crutches for myself? Why should I sit and watch to make sure AI doesn't go off the rails? Why isn't there a system that constrains AI instead of letting it create uncontrollably?
That's how Octra was born.
The birth of an idea: AI works like an unsupervised intern
One day I caught AI doing something completely different from what I asked. And it hit me: how do big companies deal with uncontrollable employees? Managers hound them from morning to night. They don't let them get creative — they set boundaries and monitor execution.
Why can't one AI control another AI the same way?
Sounds recursive, but it's a perfectly workable idea. One AI — the one that doesn't dive into details, just looks at the result and says "this is crap, redo it." A second AI — the one that does the work. A third — that reviews.
But one idea isn't enough for a whole platform. I needed something else: the agent should work on a server, interact with my GitHub, create repos and pull requests, so I could just go to sleep and wake up to a ready PR with code that passed all checks.
That's how Octra was born.
What Octra actually is
In short: Octra is a multi-agent AI orchestrator that builds software through a Boss → Manager → Worker pipeline, with every project snapshotted into the Nix store for instant rollback and zero disk consumption.
But let's unpack. Octra is not just another "AI coder." It's a structuring constraint for artificial intelligence. The project's philosophy in one sentence:
AI is a brilliant but unreliable brain. The system is the rigid shell that controls it.
Octra doesn't try to make AI "smarter." It doesn't try to teach it to "think like a senior engineer." It doesn't add creativity. Octra does the opposite: it locks AI in a cage of rules, formats, queues, roles, and checks. And inside that cage, AI works perfectly — because it has no way to stray.
This isn't a limitation. It's a feature. Octra treats AI as a reliable executor in a controlled system, not as an autonomous agent.
How the pipeline works: Boss → Manager → Worker
Octra has three roles that form a classic management hierarchy:
Boss (CTO) — receives the task from the user, estimates complexity, plans architecture, decides how many managers are needed and what kind, then verifies the result and pushes to GitHub. It doesn't write code. It only commands.
Manager (Team Lead) — receives a specific subtask and set of requirements from the Boss. Hires workers (1 to 3, depending on complexity), distributes work among them, then reviews their results and asks for rework if needed. Doesn't write code — only reviews.
Worker (Developer) — writes code. Or searches for information. Or creates documents. Does exactly one task assigned by the Manager. No authority to deviate.
Each link answers one question and doesn't meddle in another's territory. Boss doesn't descend into code. Worker doesn't decide architecture. Manager doesn't push their own ideas — they only verify the Worker did what they were told.
This is divide and conquer in its pure form: complex tasks are broken into many small, narrow AI calls. Each call answers exactly one question, with no room for creativity.
Why Octra works differently: the philosophy of control
Most AI tools try to make AI "better" — more context, smarter models, finer prompts. Octra takes the opposite approach.
JSON-only responses. Every prompt requires strictly structured output. AI doesn't narrate, explain, or explore — it answers exactly the question asked and moves on. Output format is strict JSON, no page-long reasoning.
No role-playing in system prompts. AI doesn't need to "act like a senior backend developer with 10 years of experience." It needs to follow instructions precisely and return parseable output. Role prompts only clutter context and create an illusion of competence.
Every step is validated. Boss validates the final result. Manager reviews Worker output. Failed commands are retried with error context. No output is taken on faith.
Determinism over creativity. A single low temperature (0.2) for all roles, constrained output formats, explicit rules for every decision. Predictability beats "smartness."
Context is a resource, not a history. Project context is stored not as a dialogue history, but as structured records with visibility scopes and importance flags. AI doesn't "remember" — it's told what it needs to know.
All this philosophy lives in one file — internal/config/determinism.go. Literally 151 lines of code that define how Octra works at a fundamental level: one temperature for all roles, a rigid fallback provider chain, zero options for tuning "creativity" through environment variables.
Complexity estimation: not every task needs the full pipeline
Divide-and-conquer is the right tool for complex projects, but the same mechanisms are wildly overkill for trivial tasks. "Write hello world in Python" — should Octra really spin up Boss, Manager, Worker, generating a file tree with unclear logic instead of one obvious line of code?
Octra solves this with AI complexity estimation. When there's no Canvas Workflow, the system makes a lightweight AI request that estimates the task on a scale of 1-10. Not through clever trigger-words, but through pure analysis of the work required.
If the task is trivial (score ≤ 2 by default), Octra skips the entire Boss → Manager → Worker pipeline and routes the task straight to a Universal Node — a single unconstrained AI call that returns the minimal correct result. If the Universal Node fails, the system falls back to the full pipeline.
The threshold is configurable via OCTRA_UNIVERSAL_MAX_GRADE. You can even disable it entirely — OCTRA_DISABLE_UNIVERSAL_NODE=true.
Universal Node: plain AI agent without managers and architects
Universal Node wasn't born from architectural considerations but from direct user pain.
When Octra first launched, every task — from "write hello world" to "design a microservice architecture" — went through the full Boss → Manager → Worker pipeline with complexity estimation, planning, team hiring. People wrote: "I asked for a simple script and the system spent 40 seconds thinking before outputting one line."
So Universal Node was born — a plain AI agent with minimal system prompts. No roles, no hierarchy, no planning. Just: get task → immediately return result. Minimum time, minimum tokens, minimum latency.
It has two activation paths:
Explicit Canvas node: the user places a Universal Node on the canvas — Octra executes it directly, no questions asked. AI failed? Task failed. No fallback to Boss. The user owns their workflow.
Auto mode (default): when Canvas is empty, Octra decides — simple task? Run through Universal. Complex? Launch the full pipeline. The decision is made through AI complexity estimation, not trigger words.
One more important detail: the dependencies flag. AI specifies "dependencies": true/false in its response. If code uses only standard library — Octra skips nix flake lock, saving ~37 seconds on trivial single-file tasks. Hello world is ready in 2 seconds, not 40. And this is one of those cases where micro-optimization matters — because every second of waiting breaks flow.
Search Node: AI no longer lies about facts
A question requiring an external fact — "what's the latest Go version?", "who is OpenAI's CEO?" — AI can't answer from its training data. Previously, Universal Node would answer from memory and hallucinate. Search Node solves this.
For each task, Octra runs a deterministic NeedsWebSearch() heuristic on the title + description — no AI, just signature matching: explicit requests ("find...", "search for..."), recency signals (latest, today, news), factual queries (price, who is, exchange rate, capital city), or a 20xx year. Code and math skip search — AI handles those fine on its own.
When search is needed, Octra creates a Search Node, attaches it to Universal/Boss/Manager/Worker, and performs the search. Results are ranked with BM25 (k1=1.5, b=0.75) — pure math, no neural networks.
DuckDuckGo out of the box
The first search layer is DuckDuckGo. Octra parses html.duckduckgo.com/html/ without an API key. Free, no registration required, works immediately after docker compose up. Perfect for self-deployment.
But DuckDuckGo has a ceiling: no deep research, no multi-source analysis, no reasoning. It just returns snippets. Fine for surface-level questions. Not for deep research.
Apodex: auxiliary AI model for search
The second layer is Apodex. This isn't another AI provider for code generation. It's an auxiliary model specialized specifically in search and information analysis.
Unlike regular LLMs that answer from their parameters, Apodex can:
- Search the internet in real-time — the model decides what keywords to query and returns results
- Fetch specific URLs — the model can say "I need to read this page" and receive its content
- Reason step-by-step — SSE stream broadcasts
thinking,web_search,fetch_url_content,agent_summarystages to the frontend. The user sees AI searching and thinking in real-time - Deep research — the model can perform multiple search iterations, digging deeper as it finds information
Configured in settings as an OpenAI-compatible endpoint. Octra auto-detects the format: if the URL contains /responses — it sends {"input": query}, if /chat/completions — it sends standard messages.
Custom search providers
Apodex is the default, but you can connect any OpenAI-compatible endpoint. If your model can search the internet (or you have your own search agent), just set the base-url, model, and api-key — Octra will use it for search instead of Apodex.
Same mechanism: ModelProvider sends a request, reads the SSE stream, parses choices[].delta.content for chat endpoints or output_text for Responses API, and broadcasts progress to the frontend. DuckDuckGo always works as fallback — if the AI provider is unavailable or returns empty results, HTML scraping kicks in.
Dual search and BM25
When a task reaches a worker, search runs in two threads:
- AI provider (Apodex / custom) — deep, with reasoning and reflection
- DuckDuckGo — fast, shallow, as fallback
Results are merged, de-duplicated by URL, and re-ranked with BM25. Top 8 sources are injected into the AI prompt. For non-code answers, a solution/sources.md is generated with citations for each source.
Canvas Workflow: when you want full control
Auto Mode is convenient for simple tasks. But when you're building something serious, you want to control every step.
Canvas Workflow in Octra is a visual pipeline editor built on React Flow (@xyflow/react). You literally drag nodes onto a canvas, connect them with arrows, and get your task processing pipeline.
When users place nodes on the Canvas, Octra executes exactly what's drawn. No AI planning, no complexity estimation, no fallback. The user takes full responsibility for the architecture. AI is just a tool that executes.
Canvas supports these node types:
- Universal Node — one AI call, the fastest path
- Manager — creates a team of workers, manages, reviews
- Worker — writes code / searches information / creates documents
- GitHub Node — displays GitHub integration results
You can import ready-made workflows from the library, export your own, and share them with your team.
Node types and outputs
Octra can produce four types of results:
| Type | Output | What Worker does |
|---|---|---|
code | Source code | Generates files, commits to git |
research | Markdown report | Searches the web for information |
document | Markdown document | Writes structured document |
Task type is determined by Boss in the first planning step. This is critical — different types need different prompts, different managers, and different workers. A manager for code hires developers. A manager for research hires analysts with different search angles.
Group chat for agents: how workers communicate
One of the most interesting parts of Octra is the Group Chat pattern, implementing the Microsoft Agent Framework architecture.
When multiple workers are hired for a task (e.g., frontend + backend), they don't work in isolation. Octra runs them through a Group Chat Orchestrator:
Round 1: all agents generate concurrently (AllAtOnceSelector)
Worker A → Message{files}
Worker B → Message{files}
Worker C → Message{files}
↓ broadcast
Round 2: each agent sees the entire conversation → can improve
Worker A → sees files B+C → improves theirs
Worker B → sees files A+C → improves theirs
Worker C → sees files A+B → improves theirs
↓ termination condition
git add . + git commit
How do agents "read the chat"? Each agent receives the full Conversation with all messages and files. WorkerAgent.buildChatContext() extracts files generated by other agents and inserts them into its own AI prompt — workers literally see what others built and can adapt.
The architecture supports different speaker selection strategies:
AllAtOnceSelector— all agents speak simultaneouslyRoundRobin— taking turnsRoleBased— by roleAgentBased— by specific agents
Termination is also configurable: by reaching a target round, when all agents say terminate, or by a custom condition.
Context Management: structured memory, not dialogue history
One of the main long-context problems is that AI "forgets" what happened at the beginning of a long dialogue or confuses facts because they're drowned in thousands of history tokens. Octra solves this not by growing the context window, but through structured context management.
Project context is stored in Redis (fast cache, 5-minute TTL) and PostgreSQL (permanent storage). For each AI call, the system collects relevant records and formats them into a block before the prompt.
Three visibility levels:
| Scope | Who sees it | Who sets it | Lifecycle |
|---|---|---|---|
global | All agents in project | Boss / Manager | Lives forever |
team | All workers of one manager | Manager | Until manager completes |
individual | One agent | Any agent | For the agent's session |
How it works in practice:
- Boss sends a prompt → AI returns JSON with optional
"context": {"scope": "global", "type": "global_rule", "content": "..."} - ContextService saves to PostgreSQL + Redis, then injects into all subsequent agent prompts
- Manager and Worker can also create context (team/individual scopes)
- Before each AI call,
GetForPrompt()collects all relevant context into a formatted block
Automatic cleanup:
- Messages are capped at ~20 (adaptive: 40 if average length < 200 chars, 30 if < 500)
- When limit is exceeded, the 5 oldest non-important messages are removed
- Global rules live forever until the user says "forget"
- If AI or user sends
"content": "forget", matching records are marked as forgotten
Message visibility scopes aren't just metadata. They literally determine which agents receive this information. If a Manager sets a team context, a Worker of another Manager won't see it. This is the isolation needed for parallel work of multiple teams.
Hybrid prompt filtering: determinism + AI
A huge problem when working with long prompts is context window pollution with irrelevant information. Boss receives tons of context, most of which isn't relevant to the task. This increases tokens, reduces quality, and provokes hallucinations.
Octra solves this with hybrid two-layer filtering:
Layer 1 — Deterministic (code): trigger words in the task title/description cut out obviously irrelevant prompts and connect relevant guides. For example, if the task contains "docker" — the devops-containers guide is included. If "react" — frontend-component and frontend-state are included. If the task came from a GitHub Issue — type is set to github and the github_issue prompt is added.
The trigger table is a plain JSON object in code. No AI, no magic. Just title + description → match keywords → select prompts.
Layer 2 — AI chooses from a narrowed list. The model receives not 50 prompt options, but 3-4 filtered ones, and picks what's needed for the specific task. AI doesn't get full freedom — it chooses from a controlled set.
Structure after filtering: AI receives a controlled set with or_prompts (may select), available_guides (may request), locked_prompts (always included), locked_guides (always applied).
Benefits:
| Aspect | Before (everything at once) | After (hybrid) |
|---|---|---|
| Tokens | All guides sequentially | Only selected ones |
| Relevance | Medium — AI filters itself | High — guides match the task |
| Control | AI can ignore guides | AI chooses from filtered set |
| Flexibility | None — everything is rigid | AI adapts to atypical tasks |
| Scaling | Each guide = more tokens | 100 guides possible, 2-3 selected |
This also works with model strength ranking. When Octra falls back to a weak model (gpt-4o-mini, claude-3-haiku, gemini-pro), the prompt is automatically shortened: weak models follow long instructions with examples poorly. Prompt rank (full vs light) is selected by model name — mini, haiku, flash, 8b, 7b in the model name automatically trigger a shortened prompt.
Skill Warehouse: atomic fragments instead of monolithic files
Traditional AI tools use large skill files (100+ lines each) that are sent entirely into every prompt. Octra breaks them into 46 atomic fragments of 3-6 lines each.
Skill Warehouse is a registry that supports:
Catalog()— show everything in the warehouseCatalogFiltered("Backend")— only specified categoriesSearch(role, tech, task, 3)— top 3 fragments by relevanceSelect(slugs...)— take only these fragments
Here's how it works in practice. Manager assigns roles to workers and queries the Warehouse:
Manager → Search("backend go", "go", taskDescription, 3)
→ ["backend-api", "backend-data", "backend-security"]
→ WorkerRole.SelectedSkillSlugs = [...]
Worker receives only ~15-30 lines of targeted instructions instead of 100+ lines of a monolithic file. Higher relevance, fewer tokens, better quality.
Fragment search uses BM25 — the same algorithm as Search Node. No AI, pure math: term frequency, inverse document frequency, normalization. Completely deterministic.
Fragments are grouped by category: Backend, Frontend, DevOps, Proxy, Research, VPN. Boss can pass skill_categories in task metadata — then Manager and Worker will only see the specified categories.
Tool Scaffolding: real tools inside Nix
Most AI coders just generate text that looks like code. Octra can do something better: run real toolchains inside a Nix environment.
setupProject() → FlakeBuilder(techStack) → ToolExecutor(generateViaTools)
├── npm init / cargo init / flutter create / …
├── AI generation fallback if Nix/tool unavailable
└── git status --porcelain to detect created files
FlakeBuilder generates flake.nix with Nix packages for 20+ stacks: Go (go, gopls, gotools), Python (python3, pip, black, ruff), Node.js (nodejs, typescript), Rust (rustc, cargo, rust-analyzer), PHP (php83, composer), Flutter (flutter, dart), Java (jdk, maven), and a dozen more.
ToolExecutor runs real commands: npm init, cargo init, composer create-project, flutter create — inside nix develop where all dependencies are already available. If Nix isn't available — graceful fallback to AI generation.
Commands run through a separate profile (--profile .octra/nix-profile) to cache the Nix environment between runs.
After execution, git status --porcelain detects created files, and hasRealCode() verifies they're real source code, not stubs — if the tool only generated package.json and empty files, Worker falls back to AI generation.
Command Error Auto-Fix
When a command fails with a non-zero exit code, its output is fed back to AI for automatic fixing:
Worker generates code → runs commands → exit code ≠ 0
↓
AI receives error + current files → returns fixes
↓
patches are written to disk
Only errors trigger fixes. Successful command output is ignored. Each failed command gets one fix attempt.
Command output is buffered through boundedBuffer — only the last 64KB of output is stored, so multi-hundred-megabyte build logs don't eat all memory.
Tool Guides: how Octra prevents AI from hallucinating commands
A specific pain point with AI coders is command hallucinations. AI writes npm install some-package but the package was renamed. AI writes cargo build --release but the flag is different. AI writes dotnet new mvc but the template is outdated.
Octra solves this with a toolchain registry (pkg/guids/). These aren't AI-generated instructions — they're cheat sheets written by a Go developer for each tool.
Each cheat sheet includes the name, binary, common commands, and typical project structure:
npm: Install deps → npm install | Add package → npm install <pkg> | Run script → npm run <script>
Structure: package.json / node_modules/ / src/index.ts
18 guides are registered: Go, npm, pip, Cargo, Maven, Gradle, Kotlin, dotnet, Flutter, Composer, Artisan, Bundler, Gem, Mix, Cabal, CMake, SwiftPM, Zig. Each for its own language and ecosystem.
How it works in the pipeline
When Boss recognizes the tech stack, it doesn't just say "it's Go." It:
- Goes to the
techStackGuideKeysmapping — each stack maps to a set of guides:"go" → ["Go"],"nodejs" → ["npm"],"php" → ["Composer", "Artisan"] - At the Worker stage, it injects guides directly into the prompt via
FormatCheat()— AI receives a block like:
TOOL REFERENCE — Go:
New module: go mod init <module>
Build package: go build ./...
Test: go test ./...
Add dependency: go get <module>
Typical project structure:
go.mod
go.sum
main.go
AI doesn't recall command syntax from memory — it reads them from the guide. Chance of hallucination drops to near zero.
Instralutions: project initialization presets
The second layer is Instralutions — presets for 25+ frameworks: node-react (Vite + React), rust-axum, python-django, flutter, php-laravel, spring, elixir-phoenix, and more. AI just picks a preset instead of guessing commands. After selection:
instcore.Resolve(plan.Install)turns flags into real bash commandsinstcore.ResolvePackages(plan.Install)calculates which Nix packages are missing fromflake.nixinstcore.EnsureNixPackages()patchesflake.nix, adding needed packages, and regeneratesflake.lock- Commands run through
nix developwith the updated environment
A Nix package sanitizer strips bundled tools (npm → dropped, bundled with nodejs; pip → remapped to python3Packages.pip). Without this, AI might add npm as a separate package and Nix would crash. Learned the hard way.
Why all this matters
Guides solve a fundamental problem: AI doesn't know exact toolchain syntax. It's read documentation for hundreds of tools mixed together and remembers them approximately. When given a precise cheat sheet for a specific stack, it stops inventing commands and starts using them.
It's an invisible but critical feature. It's precisely why Octra breaks builds less often than other AI coders.
Nix as a foundation: why not Docker, not Ubuntu, not just files
This is the most important architectural question, so let's examine it thoroughly.
Why Nix? Octra has a unique requirement: a project should take zero space when inactive, restore instantly, and be bit-identical to the original.
Docker won't work: images permanently occupy disk space, deduplication is at the layer level, not individual files across projects. To restore a project — you need to rebuild the image. Ubuntu won't work: apt install today and tomorrow gives different versions, no built-in snapshots, projects eat disk space continuously.
Nix solves all three problems with one architecture. Let's go step by step.
Step 1. FlakeBuilder — environment generation for your tech stack
The first step after receiving a task — FlakeBuilder generates flake.nix. This isn't some abstract template — it's an exact package map for the specific stack. Internally it's a plain Go map with 20+ stacks:
go → {build: [go], shell: [go, gopls, gotools]}
python → {build: [python3, pip], shell: [python3, pip, black, ruff]}
rust → {build: [rustc, cargo], shell: [rustc, cargo, rust-analyzer]}
node → {build: [nodejs], shell: [nodejs, typescript]}
php → {build: [php83, composer], shell: [php83, composer]}
flutter → {build: [flutter], shell: [flutter, dart]}
java → {build: [jdk, maven], shell: [jdk, maven]}
cpp → {build: [gcc, cmake], shell: [gcc, cmake, ninja, gdb]}
zig, elixir, haskell, scala, R, swift, dotnet, kotlin, ruby...
If the stack isn't found — a minimal flake is generated with zero dependencies. No unnecessary packages in the environment.
Step 2. nix develop — commands inside an isolated shell
When a Worker agent runs a toolchain, Octra wraps each command in nix develop — it runs inside a Nix environment where only the specified packages are available. No host system garbage, no floating versions. The profile (.octra/nix-profile) caches the built environment, making subsequent runs take fractions of a second.
If Nix isn't installed on the host system — NixDevelopCmd() checks exec.LookPath("nix") and gracefully falls back to sh -c. The system works without Nix too, just without isolation.
Step 3. nix flake lock — version pinning
When the project is generated, Octra runs nix flake lock in the project directory. This command creates flake.lock, which pins the exact revision of nixpkgs and all dependencies. A project built today will build with the same versions a year from now.
Optimization for trivial tasks: if the AI worker specified "dependencies": false (code uses only standard library) — nix flake lock is skipped. This saves ~37 seconds on every hello-world-style task with no external dependencies. For a simple script, version locking is unnecessary — the Nix store snapshot still guarantees reproducibility.
Step 4. nix build — build verification
After all workers finish generation, Octra runs nix build inside the project. This is an optional but extremely useful step: it verifies the project compiles and builds through Nix. If the build fails — Octra logs a warning but doesn't stop the pipeline (Nix might be unavailable, or the toolchain might not support building through Nix).
During the build, Octra parses stdout/stderr in real time (bufio.Scanner through io.MultiReader) and catches "copying path" lines with the regex /nix/store/[^-]+-(.+?)' from — to show the user which package is being downloaded: "Installing go...", "Installing python3...".
Step 5. nix-store --add — zero-disk-footprint snapshot
The most important step. After all generation completes, Octra calls snapshotProject():
- Collects all git-tracked files (via
git ls-files --cached --others --exclude-standard -z) — only what should be in the project, nonode_modules,target,dist - Copies them to a temporary directory
- Runs
nix-store --add stagingDir - Gets the store path —
/nix/store/hash-name
After this, the working project directory is deleted. The project takes zero bytes on active storage. Yet it's fully alive and restores instantly.
Deduplication: Nix store stores files by content hash. If two projects both contain package.json with identical content — there's physically one copy on disk. 1000 similar projects can take less space than one, if their files overlap.
GC root: Octra registers a root reference for each snapshot via registerGCRoot(storePath, taskID), preventing the Nix garbage collector (nix store gc) from deleting projects. Without this, nix-store --add stores the data, but it would disappear on the next GC run.
Step 6. RestoreProject — instant restoration
When a user switches to a historical chat or requests an old project, Octra calls RestoreProject(taskID):
- Finds the task in the DB by
taskID - Reads
NixStorePathfrom the model - Copies content from
/nix/store/hash/back to the working directory
This is file copying from one disk location to another. No building, no dependencies, no network requests. Restoration takes milliseconds.
If the Nix store is configured to a non-standard path (NIX_STORE variable), resolveStorePath() adjusts the path automatically — so Octra works in environments with an overridden store.
NixOS module: production-ready deployment
Octra ships as a fully featured NixOS module that can be imported with one line.
Under the hood, the module creates:
- A systemd service
octra-orchestrator, running as useroctra - User
octrais automatically added tonix trusted-users— otherwise Nix won't allownix-store --addfrom an unprivileged user - Dependencies:
postgresql.serviceandredis.service— if they're not running, Octra won't start Restart = on-failure— if the process crashes, systemd restarts it automatically- Port is configurable through an option (default 50052), environment through
environment
The result: Octra on NixOS isn't a container, not a VM, but a native systemd service that uses the Nix store as a snapshot filesystem. Docker fundamentally can't do this.
GitHub integration: auto-repos, PRs, forks, re-runs
Octra can automatically publish generated projects to GitHub. Everything is managed by two toggles in the UI:
- Publish new projects to GitHub — creates a new repository and pushes code
- Create pull requests — creates a PR for tasks linked to issues. Code is always pushed to a branch
Auto-Fork for PRs
When Octra targets a GitHub Issue but the bot account doesn't have write access to the target repo, it automatically forks the repository:
Octra detects issue URL
│
├── Has write access? → clone original → push branch → PR
│
└── No write access
├── CheckWritePermission(owner/repo) → false
├── ForkRepository(owner/repo) → fork created
├── WaitForkReady → clone fork
├── AddUpstream → SyncWithUpstream
└── Push to fork → PR from forkOwner:branch → owner:base
Cross-repo PRs use the head: "forkOwner:branchName" format. Fork information is saved in task metadata — re-runs don't create a new fork.
Reusing existing tasks
If the same issue is submitted again, Octra finds the previous task and reuses its fork:
findExistingTaskByIssue(issueURL)
│
├── Found in DB (status=done, nix_store_path != '')
│ ├── Read github_fork_owner from previous task
│ ├── Clone fork directly (skip permission check + fork creation)
│ ├── GetIssueCommentsSince(previousTask.UpdatedAt)
│ └── Inject "NEW COMMENTS" section into AI prompt
│
└── Not found → standard flow
This means: developer files a bug report → Octra makes a PR → developer writes "let's also fix this" → Octra sees new comments, clones the existing fork, and iterates. Without recreating the fork, without losing context.
gRPC: why not regular HTTP
Octra's communication architecture went through an interesting evolution.
Previously: Boss, Manager, and Worker were separate gRPC services, each with its own port, proto file, and lifecycle. Communication went through gRPC over the network.
Now: all three roles live in a single process and call each other directly through Go. What's still on gRPC:
- API Gateway → Orchestrator — gRPC-based streaming for TaskUpdate delivery
- Orchestrator → Agents Service — AI providers (Claude, Gemini, GPT, DeepSeek, Grok, Ollama)
- User Service → Orchestrator — file restoration from Nix store
- Frontend → User Service — gRPC-web (connect-web) for fetching project files
Why gRPC for these boundaries instead of HTTP?
-
Server-Sent Streaming. gRPC has built-in server streaming. Octra sends
TaskUpdatemessages in real-time — generation progress, new files, statuses. On HTTP you'd need SSE or WebSocket, each with their own problems (limited SSE support in HTTP/1.1, no binary frames, proxy issues). -
Strict contracts.
.protofiles are a contract. Client and server can't diverge in data interpretation. On REST HTTP, everyone interprets JSON differently. When you have 4 Go services and 1 TypeScript frontend, strict contracts save days of debugging. -
Bidirectional streaming for reconnect. Octra supports reconnecting to existing tasks through a dedicated endpoint. gRPC streaming allows the server to resume sending messages from where the client disconnected.
-
Protocol Buffers are more compact than JSON. For high-traffic internal channels (orchestrator → agents), protobuf compactness gives ~30-50% savings on message size.
-
HTTP/2 out of the box. Multiplexing, header compression, server push — all built in.
Stream Reliability: not a single message lost
Progress updates from the Boss → Manager → Worker pipeline are delivered through a buffered channel with 256 slots and blocking send. Not a single message is lost.
Previously, non-blocking sends with select default: silently dropped file-write messages when the channel was full. Imagine: 50 files generated, but the frontend only saw 40 — because 10 messages were silently dropped while the ws-client was briefly stalled.
Now the channel is blocking. If the client is slow — the pipeline waits. But 100% of messages arrive.
Additionally, every TaskUpdate is written to Redis Stream and Store state. If a client reconnects, it sends task_id to the /task/reconnect endpoint, and the server continues sending from the last saved state — messages aren't lost even on complete connection drops.
What's next: looking ahead
Octra is evolving toward full development autonomy. Already it can:
- Accept a task in natural language
- Design architecture
- Hire a team of AI agents
- Generate code through real toolchains
- Fix build errors
- Publish results to GitHub
- Return to a task based on new comments
Without the user writing a single line of code.
Plans: skills from Claude Code and other ecosystems
Currently Skill Warehouse contains 46 atomic fragments written by hand. But the world doesn't stand still — Claude Code has a huge skill library, Codex has its own, Cursor has its own, OpenCode has its own. Each of these ecosystems has accumulated hundreds of instructions for all sorts of scenarios.
The plan is to make Octra a skill aggregator: convert skills from Claude Code, Codex, Cursor, and other tools into Skill Warehouse fragments automatically. So a user can plug in a skill like "write a Rust crate by all the canons" from Claude Code and use it inside the Octra pipeline without manual porting.
Imagine: you place a Manager on the Canvas, tell it "use skills from Claude Code for backend," and Octra automatically pulls in the relevant fragments, converts them to its format, and injects them into workers. No copy-pasting, no manual adaptation.
This opens access to thousands of ready-made community instructions — and breaks down the wall between AI coder ecosystems.
But the key difference between Octra and other AI coders is control. Octra doesn't try to be the smartest. It tries to be the most predictable. The most reliable. The most constrained, in a good way. Because when AI can't go off the rails — it does exactly what's needed.
And that, damn it, is exactly what every other tool is missing.
Try it: octra.env.pm GitHub: github.com/Payel-git-ol/Octra
Octra: describe once, rebuild forever.
Posted Jun 23, 2026, 2:21 PM UTC