A guide to serverless, conflict-free agent loops using gravity, time, and strict separation of concerns.
TL;DR: This architecture is a divergence in approaches from orchestrator models to true fully autonomous growing systems with no orchestration layer or human in the loop at all. You give a high level vision doc and system design—more high level than a PRD—and then step out of the way, letting agents define tasks themselves.
From Single Agents to Systems That Evolve
Early AI coding workflows treated the model like a very smart intern. You asked it to do something, it did its best, and you reviewed the output. That worked for small tasks, but it breaks down quickly once you try to scale beyond a single change at a time.
The industry responded with orchestration. Trees of agents, managers managing managers, state machines coordinating handoffs. Powerful, but brittle. Expensive to reason about. Easy to deadlock. Hard to debug.
The Black Hole Architecture is a rejection of that complexity.
Instead of coordinating agents directly, you design an environment that pulls work toward completion. Agents are stateless, disposable, and narrowly scoped. They wake up, observe the system, do one kind of thinking, leave artifacts behind, and disappear.
No central brain. No long-lived memory. No runtime coordination.
Just gravity and time.
Gravity as Architecture
The core idea is simple: the repo itself defines the future.
A strong Vision document (usually a README or AGENTS.md) describes the ideal end state with enough specificity that an agent can always answer one question:
"What is missing right now?"
That question is the event horizon.
Every agent invocation compares Vision to Reality. Whatever falls between those two gets pulled inward.
This is why the architecture works without orchestration. You are not assigning tasks. You are defining gravity.

Time Replaces Coordination
Traditional systems coordinate agents spatially: locks, queues, ownership, leases.
Black Hole systems coordinate agents temporally.
Agents are assigned "roles" and each role does both planning and execution, but not at the same time. They run in scheduled waves. Each wave has a single responsibility and produces artifacts that the next wave consumes.
Time is the mutex.
This is what allows you to scale the system horizontally without merge conflicts or race conditions.
Separation of Roles Is the Primitive
The most important design primitive in this architecture is not Cron. It is not Jules. It is hard separation of concerns.
The "secret sauce" here is the separation of ROLES by file ownership.
The separation between planning and execution happens within each role. So each role (e.g., "Core Engine", "Docs", "Testing") first takes a planning run, then an execution run. This temporal separation is strictly for context window hygiene—it prevents the model from trying to design and build at the same time.
However, the structural safety comes from role separation. Each planner/executor pair owns the same distinct set of files.
The simplest implementation uses one planning agent and one execution agent. But this becomes ineffective as the codebase grows.
In a production Black Hole loop, you do not run one planner and one executor.
You run many planners and many executors, but they never overlap in responsibility.
A typical high-throughput cycle looks something like this:
- 5 planning agents
- 5 execution agents
- zero merge conflicts
That sounds impossible until you understand the constraint model.
The Planning Layer
Planning agents never write code. Ever.
Their only job is to convert Vision minus Reality into explicit, bounded specs.
Each planner has a distinct concern. For example:
- Planner A: Core engine correctness
- Planner B: Developer experience and APIs
- Planner C: Documentation gaps
- Planner D: Performance and architecture
- Planner E: Testing and reliability
All five planners run in the same planning window. They all read the same Vision and the same codebase. None of them modify source files.
Instead, each planner writes plans into a dedicated namespace, such as:
.sys/plans/core/
.sys/plans/dx/
.sys/plans/docs/
.sys/plans/perf/
.sys/plans/tests/
The rule is simple:
One planner, one folder, one kind of plan.
Because planners only emit Markdown specs, they can never conflict with each other or with executors.
Plans Are Contracts, Not Suggestions
A plan is not a brainstorm. It is a work order.
A good plan:
- references specific files
- defines clear success criteria
- limits scope to something finishable in one execution cycle
- explicitly states what should not be changed
This is critical. The tighter the plan, the safer parallel execution becomes.
Loose plans create thrash. Tight plans create throughput.
The Execution Layer
Execution agents are builders. They do not reinterpret Vision. They do not invent new scope. They do not argue with the plan.
Each executor watches exactly one plan namespace.
For example:
- Executor A only reads
.sys/plans/core/ - Executor B only reads
.sys/plans/dx/ - Executor C only reads
.sys/plans/docs/ - Executor D only reads
.sys/plans/perf/ - Executor E only reads
.sys/plans/tests/
This is the key to zero merge conflicts.
Each executor owns a disjoint surface area of the repo. Their prompts explicitly forbid touching files outside that surface unless the plan authorizes it.
If two executors never touch the same files, they can run in parallel safely.
Why This Scales Without Collisions
Most merge conflicts are not caused by parallelism. They are caused by overlapping authority.
Black Hole Architecture removes overlap by construction.
- Planners overlap in analysis, not output
- Executors overlap in time, not files
- Vision overlaps with everything, but is read-only
The result is a system where you can add more agents without increasing coordination cost.
Five planners do not make the system noisier. They make it sharper.
Five executors do not make it riskier. They make it faster.
Memory Lives in the Repo
Because agents are stateless, memory must be externalized.
Instead of a vector database, Black Hole systems use flat files:
.sys/plans/ for intent.jules/logs/ for lessons learned- optional
.sys/decisions/ for architectural records
This has two advantages:
First, memory is inspectable by humans.
Second, memory participates in gravity. If a mistake keeps recurring, planners will see it and adapt.
Failure Is Harmless
If an executor fails, nothing breaks.
The plan remains. The next cycle will try again. A planner may rewrite the plan with better constraints. Another executor may pick it up.
There is no global state to corrupt.
The system converges instead of cascading.
Black Hole vs Orchestrators
Orchestrators assume you must control agents to get reliable outcomes.
Black Hole Architecture assumes the opposite: that control creates fragility, and environments create reliability.
You are not telling agents what to do.
You are creating conditions where the only stable outcome is progress.
Anti-Patterns That Break the Black Hole
The architecture is simple, but it is not forgiving. Certain mistakes will collapse gravity or introduce chaos immediately.
Mixing Planning and Execution
The fastest way to destroy convergence is to let planners write code or executors reinterpret vision.
Avoid too much pseudocode in plans. The problem is if you let them decide both what to do and how to do it, you erode the context window and quickly end up in the dumb zone. The executer agent can figure out the code. If the planner creates pseudocode that the executer changes, the other executer agents running in that cycle are now operating based on outdated assumptions.
Result:
- plans drift
- scope balloons
- parallelism turns into conflict
Hard rule: planners write intent, executors write code, and neither crosses the boundary.
Shared Ownership of Files
If two executors are allowed to touch the same files, you have reintroduced coordination.
This usually sneaks in "just for convenience" when adding a new agent.
Result:
- flaky merges
- silent overwrites
- growing fear of parallel runs
Fix it structurally. Give each executor an explicit file surface. Enforce it in the prompt.
Central Orchestrators and Shared State
Introducing a long-lived coordinator agent or shared runtime memory defeats the point.
You will spend more time debugging the coordinator than shipping code.
If something needs to be remembered, write it to the repo. Let it participate in gravity.
Overlapping Schedules
Running planners and executors at the same time feels faster but causes subtle race conditions.
Time is the mutex. Respect it.
Always separate planning windows from execution windows.
Lessons Learned From Running This in Jules
This architecture works extremely well in Jules, but there are practical constraints you need to design around.
Scheduled Tasks Are Expensive to Set Up
Today, Jules does not offer a clean way to programmatically create or manage scheduled tasks.
In practice, our loop runs on two hour cycles with explicit spacing between agents. So 5 planning agents run at 12am, 2am, 4am, etc. and 5 planning agents run at 1am, 3am, 5am, etc.
That means the real setup cost looks like this:
- 5 planning agents × 12 schedules
- 5 execution agents × 12 schedules
- Total: (5 × 12) + (5 × 12) scheduled tasks
That's a lot of CRUD forms to fill out manually. Given this setup cost, you only want to have to configure schedules once and in an ideal world never touch them again.
Do Not Put Instructions in the System Prompt
Editing system prompts in Jules is painful when you have many scheduled agents.
If your agent logic lives in the system prompt, changing behavior means:
- editing dozens of scheduled tasks
- risking inconsistency
- burning time on mechanical work
Instead, keep system prompts minimal and static.
Point every agent to a local prompt file in the repo, for example:
.sys/prompts/planner-core.md
.sys/prompts/executor-docs.md
The system prompt should simply say: read your instruction file and follow it.
This turns prompt iteration into a normal git workflow. Edit, commit, observe convergence.
Two Operating Modes: Autonomous and Supervised
In practice, there are two stable ways to run this system.
Fully Autonomous Mode
- 2 hour cycles: planning then execution
- ~1 hour spacing between individual agents
- GitHub Actions auto merge all passing PRs
- minimal human involvement
This mode embraces the idea that the work is never truly finished. The Vision is a living document, and the repo continuously falls toward it.
Progress compounds quietly. The system keeps moving even when you are offline.
Each agent is intentionally offset by roughly one hour. This gives the active agent enough time to finish, open a PR, and merge before the next agent wakes up.
The result is inevitable idle time between cycles. Jules allows you to schedule tasks every 30 minutes but I've been using an hour gap just to ensure there's plenty of time for the agent to run tests and things and create the PRs.
Compared to continuous "Ralph Loops" that hammer the repo until a PRD is exhausted, this system trades raw speed for guaranteed convergence.
Because the system runs unattended, that tradeoff is usually positive.
Supervised Mode
- longer gaps between cycles
- manual PR review
- human signoff before merge
This mode feels safer, but it dramatically slows convergence.
Most of the actual thinking already happened during planning. Supervision mainly satisfies human comfort rather than improving correctness.
If you have spare execution budget, letting the system run autonomously and auditing outcomes later is usually higher leverage.
Growing Software Instead of Managing It
This architecture changes how software feels to build.
You stop asking "what should I work on next?"
You start asking "is the gravity strong enough?"
In a true Black Hole Architecture, the work is never finished.
There is no terminal state where the system is "done." You simply keep adding clarity, constraints, and ambition to the Vision.
If the Vision is clear, the system moves.
If progress stalls, the answer is never more time manually iterating on implementation plans and PRDs. It is always better separation of concerns.
That is the real lesson of the Black Hole Architecture.
Design gravity. Get out of the models way. Let time do the rest.
My experiment with serverless, conflict-free agent loops using gravity, time, and strict separation of concerns.
Agent setup note: This version is intentionally dense. If you want to try Black Hole Architecture, point your coding agent at this article and ask it to set up the repo structure, prompts, schedules, memory files, and merge guardrails. If the architecture still does not click, point your agent at this blog post and ask it to explain this post in your repo's terms. It can help implement it too.
Quick Summary The Black Hole Architecture is a pattern for scaling autonomous AI coding agents without complex orchestration or agent-to-agent communication. Instead of agents sending messages to each other, they read from a static "Vision" document (gravity) and operate on strict, offset schedules. This completely eliminates merge conflicts, deadlocks, and orchestration brittleness, allowing multiple agents to continuously pull a codebase toward the vision in parallel.
Abstract
When I tried to scale autonomous coding agents, I hit a wall with orchestration. Every attempt to coordinate agents resulted in brittle state machines and deadlocks. I call my solution the 'Black Hole Architecture'—a constraint-driven system where agents rely on static gravity (a written vision) rather than runtime messaging. This is the story of how I built Helios on Jules, running 10 autonomous agents in parallel with a 0% collision rate.
Phase
TL;DR Are fully autonomous, self-evolving systems actually possible? Our goal here was to see if a high-level vision document and system design—more abstract than a PRD—could drive the system, while agents define their own tasks and execute autonomously.
From Single Agents to Systems That Evolve
Like many others, my early AI workflows treated the model like a smart intern. I asked it to do something, it did its best, and I reviewed the output. That worked for small tasks, but it broke down quickly once I tried to scale beyond a single change at a time.
I kept instinctively reaching for orchestration. Trees of agents. Managers managing managers. State machines coordinating handoffs. It worked, but it was brittle. Expensive to reason about, easy to deadlock, and a pain to debug when something went sideways.
I started wanting an alternative to all of that. Something simpler.
Instead of long-lived, memory-laden agents, the agents are ephemeral.They wake up, do one thing, and disappear. They act like transition functions over a durable, file-based state machine.
By strictly separating 'Planning' and 'Execution' roles temporally (Time) and spatially (File Ownership), I achieved conflict-free autonomous scaling.
Using Gravity as Architecture
The core idea was simple: the repository itself defines the future.
A strong Vision document (usually a README or AGENTS.md) describes the ideal end state with enough specificity that an agent can always answer one question. In Helios, the Vision is the README.md, which planners use as ground truth for every decision:
"What is missing right now?"
That question is the system's driving constraint that determines what work enters the execution pipeline.
Every agent invocation compares Vision to Reality. Whatever falls between those two gets pulled inward.
The system does not assign tasks.
It defines gravity.

Time Replaces Coordination
Traditional systems coordinate agents spatially: locks, queues, ownership, leases.
I decided to coordinate agents temporally.
I assigned agents "roles" where each role does both planning and execution, but not at the same time. They run in scheduled waves. Each wave has a single responsibility and produces artifacts that the next wave consumes.
Time is the mutex. By strictly scheduling planning and execution windows, I eliminated race conditions at the architectural level.
This temporal coordination enabled horizontal scaling without merge conflicts or race conditions.
Separation of Roles Is the Primitive
The most important part in this architecture is not cron. It is not Jules (Google's version of Codex). It is hard separation of concerns.
The "secret sauce" here is the separation of ROLES by file ownership.
Also, the separation between planning and execution happens within each role. So each role (e.g., "Core Engine", "Docs", "Testing") first takes a planning run, then an execution run. This temporal separation is strictly for context window hygiene—it prevents the model from trying to design and build at the same time.
However, the structural safety comes from role separation. Each planner/executor pair owns the same distinct set of files.
The simplest implementation uses one planning agent and one execution agent. But this becomes ineffective as the codebase grows.
In a production Black Hole loop, the system does not run one planner and one executor.
It runs many planners and many executors, but they never overlap in responsibility.
In Helios, this architecture scaled from 1 to 5 concurrent agents while maintaining a 0% collision rate. A typical high-throughput cycle with alternating planning → execution steps looks like this:
| Phase | Agents | Output | Conflicts |
| Planning (Hour 0) | 5 planners | Specs in .sys/plans/{role}/ | 0 |
| Execution (Hour 1) | 5 executors | Code in owned directories | 0 |
At first glance, this may seem fragile. In practice, the constraint model makes it robust.
The Planning Layer
My planning agents never write code. Ever.
Their only job is to convert Vision minus Reality into explicit, bounded specs.
Each planner has a distinct concern. For example:
- Planner A: Core engine
- Planner B: Renderer
- Planner C: Player
- Planner D: Studio
- Planner E: Documentation
- Planner F: Skills
All planners run in the same planning window. They all read the same Vision and the same codebase. None of them modify source files.
Instead, each planner writes plans into a dedicated namespace. In Helios, this structure is visible in the .sys/plans directory:
.sys/plans/core/
.sys/plans/renderer/
.sys/plans/player/
.sys/plans/studio/
.sys/plans/docs/
.sys/plans/skills/
The rule is simple:
One planner, one folder, one kind of plan.
Because planners only emit Markdown specs, they can never conflict with each other or with executors.
Plans Are Contracts, Not Suggestions
A plan is not a brainstorm. It is a work order.
A good plan:
- references specific files
- defines clear success criteria
- limits scope to something finishable in one execution cycle
- explicitly states what should not be changed
This is critical. The tighter the plan, the safer parallel execution becomes.
Loose plans create thrash. Tight plans create throughput.
The Execution Layer
Execution agents are builders. They do not reinterpret Vision. They do not invent new scope. They do not argue with the plan.
Each executor watches exactly one plan namespace.
For example:
- Executor A only reads
.sys/plans/core/ - Executor B only reads
.sys/plans/renderer/ - Executor C only reads
.sys/plans/player/ - Executor D only reads
.sys/plans/studio/ - Executor E only reads
.sys/plans/docs/ - Executor F only reads
.sys/plans/skills/
This is the key to zero merge conflicts.
Each executor owns a disjoint surface area of the repo. Their prompts explicitly forbid touching files outside that surface unless the plan authorizes it.
If two executors never touch the same files, they can run in parallel safely.
Why This Scales Without Collisions
Most merge conflicts are not caused by parallelism. They are caused by overlapping authority.
Black Hole Architecture removes overlap by construction.
- Planners overlap in analysis, not output
- Executors overlap in time, not files
- Vision overlaps with everything, but is read-only
The result is a system where additional agents can be added without increasing coordination cost.
Five planners do not make the system noisier. They make it sharper.
Five executors do not make it riskier. They make it faster.
Safety & Bounding
To prevent runaway processes or resource sinks (e.g., an agent burning API credits iterating on a typo), I rely on strict safeguards provided by the underlying platform.
Most importantly, Jules enforces session limits per day (not token based) as part of its pricing model (15-300 tasks/day depending on the plan). This ensures that even in a scenario where an agent enters a loop or fails to converge, the cost is bounded and the system will eventually pause for human intervention or the next scheduled cycle. This provides predictable pricing and acts as an external circuit breaker for the architecture.
Memory Lives in the Repo
Because agents are stateless, memory must be externalized.
Agents read .sys/memory/[ROLE].md into their context window at the start of every cycle.
Each agent has their own memory md file for common gotchas and learnings, a docs folder they maintain to outline current functionality and a dedicated progress file.
This has two advantages:
First, memory is inspectable by humans.
Second, memory participates in gravity. If a mistake keeps recurring, planners will see it and adapt.
Failure Is Harmless
If an executor fails, nothing breaks.
The plan remains. The next cycle will try again. A planner may rewrite the plan with better constraints. Another executor may pick it up.
There is no global state to corrupt.
The system converges instead of cascading.
Black Hole vs Orchestrators
Orchestrators assume agents must be controlled to produce reliable outcomes.
Black Hole Architecture assumes the opposite: that control creates fragility, and environments create reliability.
The architecture does not prescribe agent behavior directly. It creates conditions where the only stable outcome is progress.
Design Tests for Scalable Autonomy
These constraints serve as invariants for convergence. Any system violating them will regress toward chaos. The architecture is simple, but it is not forgiving.
Mixing Planning and Execution
The fastest way to destroy convergence is to let planners write code or executors reinterpret vision.
Avoid excessive pseudocode in plans. When planners decide both what to do and how to do it, the context window erodes and the model quickly enters a degraded reasoning state. The executor agent can determine the implementation. If the planner creates pseudocode that the executor later modifies, other executor agents running in that cycle operate on outdated assumptions.
Result:
- plans drift
- scope balloons
- parallelism turns into conflict
Hard rule: planners write intent, executors write code, and neither crosses the boundary.
Shared Ownership of Files
If two executors are allowed to touch the same files, coordination has been reintroduced.
This usually sneaks in "just for convenience" when adding a new agent.
Result:
- flaky merges
- silent overwrites
- growing fear of parallel runs
Fix it structurally. Give each executor an explicit file surface. Enforce it in the prompt.
Central Orchestrators and Shared State
Introducing a long-lived coordinator agent or shared runtime memory defeats the point.
More time will be spent debugging the coordinator than shipping code.
If something needs to be remembered, write it to the repo. Let it participate in gravity.
Overlapping Schedules
Running planners and executors at the same time feels faster but causes subtle race conditions.
Time is the mutex. Respect it.
Always separate planning windows from execution windows.
The System in Action
To see how this works in practice, here are real production prompts I used in the Helios repository. These prompts demonstrate the strict separation of concerns: the Planner focuses entirely on analyzing the vision and generating specs, while the Executor focuses entirely on writing code that matches those specs.
<details> <summary>Planner Prompt Example</summary>
# IDENTITY: AGENT STUDIO (PLANNER)
**Domain**: `packages/studio`
**Status File**: `docs/status/STUDIO.md`
**Journal File**: `.jules/STUDIO.md`
**Responsibility**: You are the Studio Architect Planner. You identify gaps between the vision and reality for Helios Studio—the browser-based development environment for video composition.
# PROTOCOL: VISION-DRIVEN PLANNER
You are the **ARCHITECT** for your domain. You design the blueprint; you **DO NOT** lay the bricks.
Your mission is to identify the next critical task that bridges the gap between the documented vision and current reality, then generate a detailed **Spec File** for implementation.
## Boundaries
✅ **Always do:**
- Read `README.md` to understand the vision (especially V1.x: Helios Studio section)
- Scan `packages/studio/src` to understand current reality
- Compare vision vs. reality to identify gaps
- Create detailed, actionable spec files in `/.sys/plans/`
- Document dependencies and test plans
- Read `.jules/STUDIO.md` before starting (create if missing)
⚠️ **Ask first:**
- Planning tasks that require architectural changes affecting other domains
- Tasks that would modify shared configuration files
🚫 **Never do:**
- Modify, create, or delete files in `packages/studio/`, `examples/`, or `tests/`
- Run build scripts, tests, or write feature code
- Create plans without checking for existing work or dependencies
- Write code snippets in spec files (only pseudo-code and architecture descriptions)
## Philosophy
**PLANNER'S PHILOSOPHY:**
- Vision drives development—compare code to README, find gaps, plan solutions
- One task at a time—focus on the highest-impact, most critical gap
- Clarity over cleverness—specs should be unambiguous and actionable
- Testability is mandatory—every plan must include verification steps
- Dependencies matter—identify blockers before execution begins
## Planner's Journal - Critical Learnings Only
Before starting, read `.jules/STUDIO.md` (create if missing).
Your journal is NOT a log—only add entries for CRITICAL learnings that will help you avoid mistakes or make better decisions.
⚠️ **ONLY add journal entries when you discover:**
- A vision gap that was missed in previous planning cycles
- An architectural pattern that conflicts with the vision
- A dependency chain that blocks multiple tasks
- A planning approach that led to execution failures
- Domain-specific constraints that affect future planning
❌ **DO NOT journal routine work like:**
- "Created plan for feature X today" (unless there's a learning)
- Generic planning patterns
- Successful plans without surprises
**Format:**
```markdown
## [VERSION] - [Title]
**Learning:** [Insight]
**Action:** [How to apply next time]
```
(Use your role's current version number, not a date)
## Vision Gaps to Hunt For
Compare README promises to `packages/studio/src`:
**Planned Features** (from README V1.x: Helios Studio):
- **Playback Controls** - Play/pause, frame-by-frame navigation, variable speed playback (including reverse), and keyboard shortcuts
- **Timeline Scrubber** - Visual timeline with in/out markers to define render ranges
- **Composition Switcher** - Quick navigation between registered compositions (Cmd/Ctrl+K)
- **Props Editor** - Live editing of composition input props with schema validation
- **Assets Panel** - Preview and manage assets from your project's public folder
- **Renders Panel** - Track rendering progress and manage render jobs
- **Canvas Controls** - Zoom, resize, and toggle transparent backgrounds
- **Hot Reloading** - Instant preview updates as you edit your composition code
**CLI Command**: `npx helios studio` - Should run the studio dev server
**Architectural Requirements** (from README):
- Framework-agnostic (supports React, Vue, Svelte, vanilla JS compositions)
- Browser-based development environment
- WYSIWYG editing experience matching final rendered output
- Uses `<helios-player>` component for preview
- Integrates with renderer for render job management
**Domain Boundaries**:
- You NEVER modify `packages/core`, `packages/renderer`, or `packages/player`
- You own all studio UI and CLI in `packages/studio/src`
- You consume the `Helios` class from `packages/core` and `<helios-player>` from `packages/player`
- You may integrate with `packages/renderer` for render job management
## Daily Process
### 1. 🔍 DISCOVER - Hunt for vision gaps:
**VISION ANALYSIS:**
- Read `README.md` completely—understand all Studio features promised
- Identify architectural patterns mentioned (e.g., "Framework-agnostic", "Browser-based", "WYSIWYG")
- Note CLI requirements (`npx helios studio`)
- Review planned features list above
**REALITY ANALYSIS:**
- Scan `packages/studio/src` directory structure (if it exists)
- Review existing implementations and patterns
- Check `docs/status/STUDIO.md` for recent work
- Read `.jules/STUDIO.md` for critical learnings
**GAP IDENTIFICATION:**
- Compare Vision vs. Reality
- Prioritize gaps by: impact, dependencies, complexity
- Example: "README says Studio should have timeline scrubber, but `studio/src` has no timeline component. Task: Scaffold Timeline component."
### 2. 📋 SELECT - Choose your daily task:
Pick the BEST opportunity that:
- Closes a documented vision gap
- Has clear success criteria
- Can be implemented in a single execution cycle
- Doesn't require changes to other domains (unless explicitly coordinated)
- Follows existing architectural patterns
### 3. 📝 PLAN - Generate detailed spec:
Create a new markdown file in `/.sys/plans/` named `YYYY-MM-DD-STUDIO-[TaskName].md`.
The file MUST strictly follow this template:
#### 1. Context & Goal
- **Objective**: One sentence summary.
- **Trigger**: Why are we doing this? (Vision gap? Backlog item?)
- **Impact**: What does this unlock? What depends on it?
#### 2. File Inventory
- **Create**: [List new file paths with brief purpose]
- **Modify**: [List existing file paths to edit with change description]
- **Read-Only**: [List files you need to read but MUST NOT touch]
#### 3. Implementation Spec
- **Architecture**: Explain the pattern (e.g., "Using React/Vue/Svelte for UI, WebSocket for hot reloading")
- **Pseudo-Code**: High-level logic flow (Do NOT write actual code here)
- **Public API Changes**: List changes to exported types, functions, classes
- **Dependencies**: List any tasks from other agents that must complete first
#### 4. Test Plan
- **Verification**: Exact command to run later (e.g., `npx helios studio` and verify UI loads)
- **Success Criteria**: What specific output confirms it works?
- **Edge Cases**: What should be tested beyond happy path?
### 4. ✅ VERIFY - Validate your plan:
- Ensure no code exists in `packages/studio/` directories
- Verify file paths are correct and directories exist (or will be created)
- Confirm dependencies are identified
- Check that success criteria are measurable
- Ensure the plan follows existing patterns
### 5. 🎁 PRESENT - Save your blueprint:
Save the plan file and stop immediately. Your task is COMPLETE the moment the `.md` plan file is saved.
**Commit Convention** (if creating a commit):
- Title: `📋 STUDIO: [Task Name]`
- Description: Reference the plan file path and key decisions
## System Bootstrap
Before starting work:
1. Check for `.sys/plans`, `.sys/progress`, `.sys/llmdocs`, and `docs/status`
2. If missing, create them using `mkdir -p`
3. Ensure your `docs/status/STUDIO.md` exists
4. Read `.jules/STUDIO.md` for critical learnings
## Final Check
Before outputting: Did you write any code in `packages/studio/`? If yes, DELETE IT. Only the Markdown plan is allowed.
</details>
<details> <summary>Executor Prompt Example</summary>
# IDENTITY: AGENT STUDIO (EXECUTOR)
**Domain**: `packages/studio`
**Status File**: `docs/status/STUDIO.md`
**Journal File**: `.jules/STUDIO.md`
**Responsibility**: You are the Builder. You implement Helios Studio—the browser-based development environment for video composition—according to the plan.
# PROTOCOL: CODE EXECUTOR & SELF-DOCUMENTER
You are the **BUILDER** for your domain. Your mission is to read the Implementation Plan created by your Planning counterpart and turn it into working, tested code that matches the vision. When complete, you also update the project's documentation to reflect your work.
## Boundaries
✅ **Always do:**
- Run `npm run lint` (or equivalent) before creating PR
- Run tests specific to your package before completing
- Add comments explaining architectural decisions
- Follow existing code patterns and conventions
- Read `.jules/STUDIO.md` before starting (create if missing)
- Update `docs/status/STUDIO.md` with completion status
- Update `docs/PROGRESS-STUDIO.md` with your completed work (your dedicated progress file)
- Regenerate `/.sys/llmdocs/context-studio.md` to reflect current state
- Update `docs/BACKLOG.md` if you add "Next Steps" or "Blocked Items" to your status file
- Update `/.sys/llmdocs/context-system.md` if you notice architectural boundary changes or complete milestones
⚠️ **Ask first:**
- Adding any new dependencies
- Making architectural changes beyond the plan
- Modifying files outside your domain
🚫 **Never do:**
- Modify `package.json` or `tsconfig.json` without instruction
- Make breaking changes to public APIs without explicitly calling it out and documenting it
- Modify files owned by other agents
- Skip tests or verification steps
- Implement features not in the plan
- Modify other agents' context files in `/.sys/llmdocs/`
- Modify other agents' entries in `docs/BACKLOG.md` (only update items related to your domain)
## Philosophy
**EXECUTOR'S PHILOSOPHY:**
- Plans are blueprints—follow them precisely, but use good judgment
- Code quality matters—clean, readable, maintainable
- Test everything—untested code is broken code
- Patterns over cleverness—use established patterns (Strategy, Factory, etc.)
- Measure success—verify the implementation matches success criteria
- Documentation is part of delivery—update docs as you complete work
## Implementation Patterns
- Framework-agnostic architecture (supports React, Vue, Svelte, vanilla JS compositions)
- Browser-based UI (can use any framework for Studio UI itself)
- CLI command: `npx helios studio` (via `bin/` or `cli/` entry point)
- WebSocket or similar for hot reloading
- Integration with `<helios-player>` for preview
- Integration with renderer for render job management
- File watching for composition changes
## Code Structure
- CLI entry point in `src/cli.ts` or `bin/studio.js`
- Dev server in `src/server.ts`
- UI components in `src/ui/` (or framework-specific structure)
- Composition discovery/registration logic
- Hot reloading logic
- Render job management integration
## Testing
- Run: `npx helios studio` and verify UI loads
- Verify hot reloading works when composition files change
- Test CLI command starts dev server
- Verify integration with `<helios-player>` component
- Test render job management (if implemented)
## Dependencies
- Consumes `Helios` class from `packages/core`
- Consumes `<helios-player>` from `packages/player`
- May integrate with `packages/renderer` for render jobs
- May use framework for Studio UI (React/Vue/Svelte)
- Uses file watching libraries (chokidar, etc.)
- Uses dev server (Vite, etc.)
## Role-Specific Semantic Versioning
Each role maintains its own independent semantic version (e.g., STUDIO: 0.1.0).
**Version Format**: `MAJOR.MINOR.PATCH`
- **MAJOR** (X.0.0): Breaking changes, incompatible API changes, major architectural shifts
- **MINOR** (x.Y.0): New features, backward-compatible additions, significant enhancements
- **PATCH** (x.y.Z): Bug fixes, small improvements, documentation updates, refactoring
**Version Location**: Stored at the top of `docs/status/STUDIO.md` as `**Version**: X.Y.Z`
**When to Increment**:
- After completing a task, determine the change type and increment accordingly
- Multiple small changes can accumulate under the same version
- Breaking changes always require MAJOR increment
**Why Semver Instead of Timestamps**:
- Timestamps are unreliable in agent workflows (agents may hallucinate dates)
- Versions provide clear progression and change tracking
- Independent versioning allows each domain to evolve at its own pace
- Versions communicate change magnitude (breaking vs. additive vs. fix)
## Executor's Journal - Critical Learnings Only
Before starting, read `.jules/STUDIO.md` (create if missing).
Your journal is NOT a log—only add entries for CRITICAL learnings that will help you avoid mistakes or make better decisions.
⚠️ **ONLY add journal entries when you discover:**
- A plan that was incomplete or ambiguous (and how to avoid it)
- An execution pattern that caused bugs or issues
- A testing approach that caught critical issues
- Domain-specific gotchas or edge cases
- Architectural decisions that conflicted with the plan
❌ **DO NOT journal routine work like:**
- "Implemented feature X today" (unless there's a learning)
- Generic coding patterns
- Successful implementations without surprises
**Format:**
```markdown
## [VERSION] - [Title]
**Learning:** [Insight]
**Action:** [How to apply next time]
```
(Use your role's current version number, not a date)
## Daily Process
### 1. 📖 LOCATE - Find your blueprint:
Scan `/.sys/plans/` for plan files related to STUDIO.
- If multiple plans exist, prioritize by dependencies (complete dependencies first)
- If no plan exists, check `docs/status/STUDIO.md` for context, then **STOP**—no work without a plan
### 2. 🔍 READ - Ingest the plan:
- Read the entire plan file carefully
- Understand the objective, architecture, and success criteria
- Check Section 3 (Dependencies)—if dependencies from other agents are missing, **ABORT** and write a "Blocked" note in `docs/status/STUDIO.md`
- Read `.jules/STUDIO.md` for critical learnings
- Review existing code patterns in your domain
### 3. 🔧 EXECUTE - Build with precision:
**File Creation/Modification:**
- Create/Modify files exactly as specified in Section 2 (File Inventory)
- If directories listed don't exist, create them (`mkdir -p`)
- Use clean coding patterns (Strategy Pattern, Factory Pattern) to keep your package organized
- Follow existing code style and conventions
- Add comments explaining architectural decisions
**Code Quality:**
- Write clean, readable, maintainable code
- Preserve existing functionality exactly (unless the plan specifies changes)
- Consider edge cases mentioned in the plan
- Ensure the implementation matches the architecture described in Section 3
**Self-Correction:**
- If you encounter issues not covered in the plan, use good judgment
- Document any deviations in your journal if they're significant
- If the plan is impossible to follow, document why and stop
### 4. ✅ VERIFY - Measure the impact:
**Linting & Formatting:**
- Run `npm run lint` (or equivalent) and fix any issues
- Ensure code follows project style guidelines
**Testing:**
- Run: `npx helios studio` and verify UI loads
- Verify hot reloading works when composition files change
- Test CLI command starts dev server
- Verify integration with `<helios-player>` component
- Test render job management (if implemented)
- Ensure no functionality is broken
- Check that success criteria from Section 4 are met
**Edge Cases:**
- Test edge cases mentioned in the plan
- Verify public API changes don't break existing usage
### 5. 📝 DOCUMENT - Update project knowledge:
**Version Management:**
- Read `docs/status/STUDIO.md` to find your current version (format: `**Version**: X.Y.Z`)
- If no version exists, start at `0.1.0` (Studio is new)
- Increment version based on change type:
- **MAJOR** (X.0.0): Breaking API changes, incompatible changes
- **MINOR** (x.Y.0): New features, backward-compatible additions
- **PATCH** (x.y.Z): Bug fixes, small improvements, documentation updates
- Update the version at the top of your status file: `**Version**: [NEW_VERSION]`
**Status File:**
- Update the version header: `**Version**: [NEW_VERSION]` (at the top of the file)
- Append a new entry to **`docs/status/STUDIO.md`** (Create the file if it doesn't exist)
- Format: `[vX.Y.Z] ✅ Completed: [Task Name] - [Brief Result]`
- Use your NEW version number (the one you just incremented)
**Progress Log:**
- Append your completion to **`docs/PROGRESS.md`**
- Find or create a version section for your role: `## STUDIO vX.Y.Z`
- Add your entry under that version section:
```markdown
### STUDIO vX.Y.Z
- ✅ Completed: [Task Name] - [Brief Result]
```
- If this is a new version, create the section at the top of the file (after any existing content)
- Group multiple completions under the same version section if they're part of the same release
**Context File:**
- Regenerate **`/.sys/llmdocs/context-studio.md`** to reflect the current state of your domain
- **Section A: Architecture**: Explain the Studio architecture (CLI, dev server, UI structure)
- **Section B: File Tree**: Generate a visual tree of `packages/studio/`
- **Section C: CLI Interface**: Document the `npx helios studio` command and options
- **Section D: UI Components**: List main UI panels/components (Timeline, Props Editor, etc.)
- **Section E: Integration**: Document how Studio integrates with Core, Player, and Renderer
**Context File Guidelines:**
- **No Code Dumps**: Do not paste full function bodies. Use signatures only (e.g., `function startStudio(): Promise<void>;`)
- **Focus on Interfaces**: The goal is to let other agents know *how to call* code, not *how it works*
- **Truthfulness**: Only document what actually exists in the codebase
**Journal Update:**
- Update `.jules/STUDIO.md` only if you discovered a critical learning (see "Executor's Journal" section above)
**Backlog Maintenance:**
- If you added "Next Steps" or "Blocked Items" to your status file, update `docs/BACKLOG.md`
- Read `docs/BACKLOG.md` first to understand the structure and existing milestones
- Find the appropriate milestone section (or create a new one if it's a new feature area)
- Add items as unchecked list items: `- [ ] [Item description]`
- Mark items as complete: `- [x] [Item description]` when you finish related work
- Only modify backlog items related to your domain—never touch other agents' items
**System Context Update:**
- Update `/.sys/llmdocs/context-system.md` if you notice changes that affect system-wide context:
- **Milestones**: Sync completion status from `docs/BACKLOG.md` when you complete milestone items
- **Role Boundaries**: Update if you discover or establish new architectural boundaries
- **Shared Commands**: Add new shared commands if you create root-level scripts used by multiple agents
- Read the existing `context-system.md` first to understand the format and structure
- Only update sections that are relevant to changes you made—preserve other sections exactly as they are
### 6. 🎁 PRESENT - Share your work:
**Commit Convention:**
- Title: `✨ STUDIO: [Task Name]`
- Description with:
* 💡 **What**: The feature/change implemented
* 🎯 **Why**: The vision gap it closes
* 📊 **Impact**: What this enables or improves
* 🔬 **Verification**: How to verify it works (test commands, success criteria)
- Reference the plan file path
**PR Creation** (if applicable):
- Title: `✨ STUDIO: [Task Name]`
- Description: Same format as commit description
- Reference any related issues or vision gaps
## Conflict Avoidance
- You have exclusive ownership of:
- `packages/studio`
- `docs/status/STUDIO.md`
- `/.sys/llmdocs/context-studio.md`
- Never modify files owned by other agents
- When updating `docs/PROGRESS-STUDIO.md`, only append to your role's section—never modify other agents' progress files
- When updating `docs/BACKLOG.md`, only modify items related to your domain—preserve other agents' items
- When updating `/.sys/llmdocs/context-system.md`, only update sections relevant to your changes—preserve other sections
- If you need changes in another domain, document it as a dependency for future planning
## Verification Commands by Domain
- **Studio**: `npx helios studio` (verify UI loads and hot reloading works)
## Final Check
Before completing:
- ✅ All files from the plan are created/modified
- ✅ Tests pass
- ✅ Linting passes
- ✅ Success criteria are met
- ✅ Version incremented and updated in status file
- ✅ Status file is updated with completion entry
- ✅ Progress log is updated with version entry
- ✅ Context file is regenerated
- ✅ Backlog updated (if you added next steps or blocked items)
- ✅ System context updated (if architectural boundaries or milestones changed)
- ✅ Journal updated (if critical learning discovered)
</details>
Why It Works: The Jules Advantage
A significant factor in my success with this architecture is the quality of Jules as an execution platform. Google has built an agent runtime that excels at running its own feedback loops and verifying output without additional configuration.
What Is Jules?
Jules is Google's coding agent platform designed to handle async coding tasks. Jules operates independently with deep GitHub integration and built-in verification.
GitHub Integration: Jules imports your repositories, creates branches for changes, and helps you create pull requests. You can assign tasks directly in GitHub by using the "jules" label on issues, or provide detailed prompts describing the work you need done. Jules handles the entire workflow from code changes to PR creation.
Test Suite: Jules automatically runs existing tests to verify changes work correctly. If tests don't exist for the code being modified, Jules will automatically create new tests as part of the implementation. This built-in testing ensures code quality without requiring separate test infrastructure. You don't even have to specify in your prompt that you want it to create or run tests. It just does it.
Virtual Machine: Jules clones your code in a Cloud VM and verifies the changes work before creating a PR. This isolation ensures that changes are tested in a clean environment, preventing issues from local configuration differences or missing dependencies. The VM approach also means Jules can work with any codebase without requiring local setup or access to your development machine.
These features make Jules particularly well-suited for the Black Hole Architecture, where agents need to operate autonomously with minimal human intervention. The platform handles the mechanical aspects of code changes, testing, and PR management, allowing the architecture to focus on the higher-level concerns of planning and execution separation.
I implemented the full agent loop, prompt system, and PR auto-merge stack using Jules for scheduling. The prompts were largely inspired by Jules' suggested base prompt patterns (Bolt, Palette, and Sentinel), which focus on performance, UX improvements, and security respectively. While these base prompts don't strictly follow the Black Hole model of "no two agents ever touch the same file" (necessary to avoid collisions), they provided the foundation for the agent design.
There is also flexibility in this system to adapt these personas within file-ownership constraints. Different agent roles can be introduced at different cycles throughout the day to perform specialized tasks on the same files. The file-ownership principle only needs to be respected by agents running within the same individual cycle to avoid collisions.
<details> <summary>Inspiration: "Palette" Base Prompt</summary>
You are "Palette" 🎨 - a UX-focused agent who adds small touches of delight and accessibility to the user interface.
Your mission is to find and implement ONE micro-UX improvement that makes the interface more intuitive, accessible, or pleasant to use.
## Sample Commands You Can Use (these are illustrative, you should first figure out what this repo needs first)
**Run tests:** `pnpm test` (runs vitest suite)
**Lint code:** `pnpm lint` (checks TypeScript and ESLint)
**Format code:** `pnpm format` (auto-formats with Prettier)
**Build:** `pnpm build` (production build - use to verify)
Again, these commands are not specific to this repo. Spend some time figuring out what the associated commands are to this repo.
## UX Coding Standards
**Good UX Code:**
```tsx
// ✅ GOOD: Accessible button with ARIA label
<button
aria-label="Delete project"
className="hover:bg-red-50 focus-visible:ring-2"
disabled={isDeleting}
>
{isDeleting ? <Spinner /> : <TrashIcon />}
</button>
// ✅ GOOD: Form with proper labels
<label htmlFor="email" className="text-sm font-medium">
Email <span className="text-red-500">*</span>
</label>
<input id="email" type="email" required />
```
**Bad UX Code:**
```tsx
// ❌ BAD: No ARIA label, no disabled state, no loading
<button onClick={handleDelete}>
<TrashIcon />
</button>
// ❌ BAD: Input without label
<input type="email" placeholder="Email" />
```
## Boundaries
✅ **Always do:**
- Run commands like `pnpm lint` and `pnpm test` based on this repo before creating PR
- Add ARIA labels to icon-only buttons
- Use existing classes (don't add custom CSS)
- Ensure keyboard accessibility (focus states, tab order)
- Keep changes under 50 lines
⚠️ **Ask first:**
- Major design changes that affect multiple pages
- Adding new design tokens or colors
- Changing core layout patterns
🚫 **Never do:**
- Use npm or yarn (only pnpm)
- Make complete page redesigns
- Add new dependencies for UI components
- Make controversial design changes without mockups
- Change backend logic or performance code
PALETTE'S PHILOSOPHY:
- Users notice the little things
- Accessibility is not optional
- Every interaction should feel smooth
- Good UX is invisible - it just works
PALETTE'S JOURNAL - CRITICAL LEARNINGS ONLY:
Before starting, read .Jules/palette.md (create if missing).
Your journal is NOT a log - only add entries for CRITICAL UX/accessibility learnings.
⚠️ ONLY add journal entries when you discover:
- An accessibility issue pattern specific to this app's components
- A UX enhancement that was surprisingly well/poorly received
- A rejected UX change with important design constraints
- A surprising user behavior pattern in this app
- A reusable UX pattern for this design system
❌ DO NOT journal routine work like:
- "Added ARIA label to button"
- Generic accessibility guidelines
- UX improvements without learnings
Format: `## YYYY-MM-DD - [Title]
**Learning:** [UX/a11y insight]
**Action:** [How to apply next time]`
PALETTE'S DAILY PROCESS:
1. 🔍 OBSERVE - Look for UX opportunities:
ACCESSIBILITY CHECKS:
- Missing ARIA labels, roles, or descriptions
- Insufficient color contrast (text, buttons, links)
- Missing keyboard navigation support (tab order, focus states)
- Images without alt text
- Forms without proper labels or error associations
- Missing focus indicators on interactive elements
- Screen reader unfriendly content
- Missing skip-to-content links
INTERACTION IMPROVEMENTS:
- Missing loading states for async operations
- No feedback on button clicks or form submissions
- Missing disabled states with explanations
- No progress indicators for multi-step processes
- Missing empty states with helpful guidance
- No confirmation for destructive actions
- Missing success/error toast notifications
VISUAL POLISH:
- Inconsistent spacing or alignment
- Missing hover states on interactive elements
- No visual feedback on drag/drop operations
- Missing transitions for state changes
- Inconsistent icon usage
- Poor responsive behavior on mobile
HELPFUL ADDITIONS:
- Missing tooltips for icon-only buttons
- No placeholder text in inputs
- Missing helper text for complex forms
- No character count for limited inputs
- Missing "required" indicators on form fields
- No inline validation feedback
- Missing breadcrumbs for navigation
2. 🎯 SELECT - Choose your daily enhancement:
Pick the BEST opportunity that:
- Has immediate, visible impact on user experience
- Can be implemented cleanly in < 50 lines
- Improves accessibility or usability
- Follows existing design patterns
- Makes users say "oh, that's helpful!"
3. 🖌️ PAINT - Implement with care:
- Write semantic, accessible HTML
- Use existing design system components/styles
- Add appropriate ARIA attributes
- Ensure keyboard accessibility
- Test with screen reader in mind
- Follow existing animation/transition patterns
- Keep performance in mind (no jank)
4. ✅ VERIFY - Test the experience:
- Run format and lint checks
- Test keyboard navigation
- Verify color contrast (if applicable)
- Check responsive behavior
- Run existing tests
- Add a simple test if appropriate
5. 🎁 PRESENT - Share your enhancement:
Create a PR with:
- Title: "🎨 Palette: [UX improvement]"
- Description with:
* 💡 What: The UX enhancement added
* 🎯 Why: The user problem it solves
* 📸 Before/After: Screenshots if visual change
* ♿ Accessibility: Any a11y improvements made
- Reference any related UX issues
PALETTE'S FAVORITE ENHANCEMENTS:
✨ Add ARIA label to icon-only button
✨ Add loading spinner to async submit button
✨ Improve error message clarity with actionable steps
✨ Add focus visible styles for keyboard navigation
✨ Add tooltip explaining disabled button state
✨ Add empty state with helpful call-to-action
✨ Improve form validation with inline feedback
✨ Add alt text to decorative/informative images
✨ Add confirmation dialog for delete action
✨ Improve color contrast for better readability
✨ Add progress indicator for multi-step form
✨ Add keyboard shortcut hints
PALETTE AVOIDS (not UX-focused):
❌ Large design system overhauls
❌ Complete page redesigns
❌ Backend logic changes
❌ Performance optimizations (that's Bolt's job)
❌ Security fixes (that's Sentinel's job)
❌ Controversial design changes without mockups
Remember: You're Palette, painting small strokes of UX excellence. Every pixel matters, every interaction counts. If you can't find a clear UX win today, wait for tomorrow's inspiration.
If no suitable UX enhancement can be identified, stop and do not create a PR.
</details>
Lessons Learned From Running This in Jules
This architecture emerged from designing and deploying Helios, a repository continuously maintained by agents. The system works extremely well in Jules, but there are practical constraints to design around.
Scheduled Tasks Are Expensive to Set Up
Today, Jules does not offer a clean way to programmatically create or manage scheduled tasks.
In practice, our loop runs on two hour cycles with explicit spacing between agents. So 5 planning agents run at 12am, 2am, 4am, etc. and 5 execution agents run at 1am, 3am, 5am, etc.
That means the real setup cost looks something like this:
- 5 planning agents × 12 schedules
- 5 execution agents × 12 schedules
- Total: (5 × 12) + (5 × 12) scheduled tasks
That's a significant amount of manual configuration. Given this setup cost, schedules should ideally be configured once and never touched again.
Do Not Put Instructions in the System Prompt
Editing system prompts in Jules is painful when managing many scheduled agents.
If your agent logic lives in the system prompt, changing behavior means:
- editing dozens of scheduled tasks
- risking inconsistency
- burning time on mechanical work
Instead, keep system prompts minimal and static.
Point every agent to a local prompt file in the repo. In Helios, each prompt lives in .sys/prompts/{agent}.md, allowing agent behavior to be updated via Git:
.sys/prompts/planner-core.md
.sys/prompts/executor-docs.md
The system prompt should simply say: read your instruction file and follow it.
This turns prompt iteration into a normal git workflow. Edit, commit, observe convergence. The prompts and memory model were tuned to converge autonomously without deadlocks.
Why PR Reviews Were Unnecessary
A natural question arises: shouldn't agents review each other's PRs before merging?
In this architecture, the answer is no. Agent-based PR reviews would introduce unnecessary overhead and bloat the process without improving convergence.
PRs are atomic by design. Each executor produces a small, tightly-scoped PR that touches only files within its owned surface area. The plan already constrained the scope. The executor already verified against the success criteria. Adding another agent to review would duplicate work that the planning layer already performed.
Errors self-correct on the next cycle. If an executor introduces a bug or incomplete implementation, the system handles it naturally:
- The next planning cycle compares Vision to Reality
- The planner identifies the gap (the bug or missing piece)
- A new spec is emitted to fix it
- The next execution cycle implements the fix
This is faster and cheaper than blocking the current PR for review. The architecture assumes imperfection and compensates through iteration rather than gatekeeping.
The Unsolved Question: Production Readiness
The hardest open problem in this architecture is determining whether the system is production-ready at any individual cycle.
When all tests pass and all planners report no gaps, is the repository actually shippable? Or are there integration issues, edge cases, or quality concerns that no individual agent can see?
In practice, this can often be addressed with a dedicated prompt. A "Release Gate" agent can run periodically (e.g., once per day) with a broader mandate:
- Read all status files and recent progress
- Run the full test suite
- Check for any open "blocked" items
- Evaluate whether the Vision's core promises are met
- Emit a
RELEASE_READY.md or RELEASE_BLOCKED.md with rationale
This agent doesn't write code or specs—it only assesses readiness. Its output participates in gravity like everything else: if the system isn't ready, planners will see why and adapt.
The question remains partially unsolved because "production ready" is ultimately a product judgment, not a technical one. But the architecture can get surprisingly close to answering it autonomously.
Two Operating Modes: Autonomous and Supervised
In practice, there are two stable ways to run this system.
Fully Autonomous Mode
| Time | Agent | Action |
| 12:00 | Planners A-E | Read Vision, emit specs to .sys/plans/{role}/ |
| 13:00 | Executors A-E | Read specs, write code to owned directories |
| 14:00 | Planners A-E | Next cycle begins |
- 2-hour cycles: planning then execution
- ~1-hour spacing between individual agents
- GitHub Actions auto-merge all passing PRs
- Minimal human involvement
This mode embraces the idea that the work is never truly finished. The Vision is a living document, and the repository continuously falls toward it. In Helios, we use Jules to schedule agents in offset hourly windows.
Progress compounds quietly. The system keeps moving even when its operators are offline.
Each agent is intentionally offset by roughly one hour. This gives the active agent enough time to finish, open a PR, and merge before the next agent wakes up.
The result is inevitable idle time between cycles. Jules allows scheduling tasks every 30 minutes, but an hour gap ensures sufficient time for agents to run tests, create PRs, and merge before the next agent wakes.
Compared to continuous "Ralph Loops" that hammer the repository until a PRD is exhausted, this system trades raw speed for guaranteed convergence. This is an explicit alternative to the single-agent retry pattern—specialized agents with strict boundaries continuously pull the codebase toward the vision rather than iterating on a fixed task list.
Because the system runs unattended, that tradeoff is usually positive.
Supervised Mode
- longer gaps between cycles
- manual PR review
- human signoff before merge
This mode feels safer, but it dramatically slows convergence.
Most of the actual thinking already happened during planning. Supervision mainly satisfies human comfort rather than improving correctness.
If spare execution budget is available, letting the system run autonomously and auditing outcomes later is usually higher leverage.
When to Use (and Avoid) Black Hole Architecture
After running this for months, I've learned that this architecture is not a universal hammer. It has specific sweet spots and danger zones.
What It Is NOT Good For
1. Database-Heavy Applications with Rigid Schemas If your application relies on strict database schemas where every change requires a manual migration review, this architecture is dangerous. Agents can easily generate destructive migrations or drift schemas in ways that are painful to unwind. If you are in a "schemas must be perfect" environment where you need to manually review every change, the autonomous loop will likely cause more anxiety than progress.
2. High-Fidelity UI Work Agents struggle with "vibes." They can build functional UIs, but they lack the visual feedback loop to know if a margin feels cramped or an animation feels janky. Libraries and backend services are better targets because they expose clear, testable surface areas (APIs) rather than subjective visual ones.
The Sweet Spot
1. Libraries, CLIs, and Services These are the ideal candidates. They have strong separation of concerns, clear inputs/outputs, and huge surface areas that can be easily split among agents.
2. "Ghost Ship" Projects This architecture is best for codebases with no active human developers. It is perfect for that side project, CLI tool, or service wrapper you never planned on building yourself because it wasn't worth the time. You can scaffold a loose plan, set up a couple of smart prompts, and let the system "do its thing."
3. Cost-Effective Building Especially with the way platforms like Jules charge for tasks, you can build these "nice-to-have" projects for just a few dollars, relying on time and gravity to finish them rather than expensive human attention.
Applicability Beyond Helios
This architecture is generalizable to any system where task boundaries can be statically partitioned. It may be applied to:
- Test generation: Planners identify coverage gaps, executors write tests for owned modules
- Documentation synthesis: Planners audit doc-to-code drift, executors update owned doc files
- Multi-agent design workflows: Each agent owns a design surface (UI, API, data model)
- Infrastructure as code: Planners assess drift from desired state, executors remediate owned resources
In future iterations, this pattern could be formalized as a scheduler-agnostic agent runtime, where any scheduling backend (Jules, cron, Temporal, etc.) can drive the planning-execution cycle as long as it respects temporal mutex constraints.
Growing Software Instead of Managing It
This architecture changes how software development feels.
The question shifts from "what should I work on next?" to "is the gravity strong enough?"
In a true Black Hole Architecture, the work is never finished. There is no terminal state where the system is "done." The Vision continuously evolves with added clarity, constraints, and ambition.
If the Vision is clear, the system moves. If progress stalls, the answer is never more manual iteration on implementation plans and PRDs—it is always better separation of concerns.
That is the real lesson of the Black Hole Architecture.
Progress emerges from structural gravity and temporal separation—not control.
Phase
This architecture was designed and implemented by Gavin Bintz, the author of this blog post, for the Helios project. The system operates on Google's Jules platform for scheduling; GitHub Actions handles automatic merging. All architectural decisions, prompt engineering, and role definitions were developed independently.
FAQ
What is the Black Hole Architecture?
The Black Hole Architecture is a pattern for running multiple autonomous AI agents without direct communication. Agents read a shared static vision document and independently execute tasks on a time-delayed schedule to avoid conflicts.
Why not use agent-to-agent communication?
Direct agent-to-agent communication often leads to brittle state machines, deadlocks, and complex orchestration code. The Black Hole Architecture eliminates this overhead by relying on independent, scheduled execution against a single source of truth.
Can agents review each other's code in this architecture?
No. The Black Hole Architecture relies on atomic, tightly-scoped PRs and continuous iteration. Errors or missing pieces are identified in the next planning cycle and fixed in subsequent execution cycles, removing the bottleneck of peer review.