PF-06 · AI · FastAPI
AetherCrew: a virtual company of 11 AI employees
A hand-built orchestrator that assigns work, picks models, and tracks cost for 11 AI employees in a virtual company. Agent work is simulated and no language model API is called.
- Role
- Design and implementation
- Period
- Personal project · released Nov 2026
- Cloud
- None
- Scale
- 11 AI employees · 3 divisions · 8 dashboard pages
- Key tech
- Python · FastAPI · WebSocket · pytest · Slack · Jira · GitHub
- 11
- AI employees
- 3
- Divisions
- 8
- Dashboard pages
At a glance
Problem
When AI employees split work by role, code must control which model each one uses, how much has been spent, and what can be written to outside systems.
Approach
The chief of staff takes a CEO directive, writes a plan, and splits it into tasks by role. Each employee has a priority list of Anthropic, OpenAI, Google, and DeepSeek models and moves to the next on failure. Estimated costs add up, with warnings at 80% and 95% and work stopped at 100%. External writes are off by default, and file access stays inside the project root.
Result
Eight FastAPI dashboard pages show the org chart, cost, logs, and a pixel-art CCTV office. It runs with no API keys and calls no language model, so it produces no real work output. The Slack, Jira, and GitHub clients are real code and run only when INTEGRATIONS_LIVE_WRITE is on.
Up close
Model fallback
What this code does: Takes an employee’s model priority list and a set of unavailable models, checks them in order from the front, and picks the first model that can be used. Skipped models are recorded in fallbacks, so it is clear which choice the work fell back to, and an empty list or a fully blocked list raises an error instead of passing silently. It checks only as many entries as the list holds, so fallback can never loop forever.
class FallbackManager:
"""Selects next available agent with bounded fallback traversal."""
def select(
self,
priority_list: list[str],
unavailable_agents: set[str] | None = None,
) -> FallbackResult:
if not priority_list:
raise ValueError("priority_list must not be empty")
blocked = unavailable_agents or set()
fallbacks: list[str] = []
for idx, model in enumerate(priority_list):
if model in blocked:
fallbacks.append(model)
continue
return FallbackResult(selected_agent=model, selected_index=idx, fallbacks=fallbacks)
raise RuntimeError("All agents are unavailable; fallback exhausted")
Budget states
What this code does: Adds up every recorded cost, computes usage against the budget, and returns one of four states: OK, WARN_80, WARN_95, or HARD_STOP. A budget set to zero or below counts as 100% used and becomes HARD_STOP at once, so a budget typo can never turn into unlimited spending. The orchestrator blocks new work while the state is HARD_STOP.
@property
def total_cost(self) -> float:
return round(sum(e.cost_usd for e in self.entries), 6)
def percent_used(self) -> float:
if self.budget_policy.total_budget <= 0:
return 100.0
return (self.total_cost / self.budget_policy.total_budget) * 100
def budget_state(self) -> str:
pct = self.percent_used()
if pct >= self.budget_policy.hard_stop_at_pct:
return "HARD_STOP"
if pct >= self.budget_policy.warn_at_pct[1]:
return "WARN_95"
if pct >= self.budget_policy.warn_at_pct[0]:
return "WARN_80"
return "OK"What I learned
When I let agents hand work to each other, a wrong result from one agent was trusted as-is by the next, with no check in between. That is when I felt that trust boundaries and permission scope must live in code, not in a polite request inside a prompt. So in this project, every point where risk can arise, such as model choice, budget stops, external writes, and file access, is a rule in code. External writes are blocked by default and allowed only when a setting is turned on, and the budget warns at 80% and 95% and stops at 100%. The more work AI takes on, the more the human decision shifts from what to ask for to how far to allow it.