3ccc723cd4 v0.17.0 — Wave 3: sandbox DB, DB isolation, mobile UI, cloud auth, X account, roadmap engine (#303)
* feat(sandbox): throwaway per-agent Postgres/Redis sandbox containers

Orchestrator-provisioned sibling containers per agent spawn
(SandboxProvisioner, roboco/runtime/sandbox.py). Per-project opt-in via
projects.sandbox_services (migration 057); master switch
ROBOCO_SANDBOX_DB_ENABLED, default-off, armed in the NAS compose only.

When active, ROBOCO_TEST_DB_* / ROBOCO_TEST_REDIS_* point at the sandbox
and the prod-creds gate-env injection is suppressed (sandbox replaces,
never coexists). Sandbox lifetime tracks the agent container: teardown at
every removal path, orphan janitor at startup + each reaper tick with a
grace window for mid-flight spawns. The pre-spawn stale-clear spares the
just-provisioned sandbox; provision pre-clears stale same-named
containers from a crash-missed teardown.

Panel: per-project sandbox-service switches in the edit dialog + feature
flag card entry.

* docs: CLAUDE.md entry for the sandboxed dev DB/Redis subsystem

* feat(security): isolate prod Postgres/Redis from agent containers (roboco_data network)

Second user-defined bridge roboco_data carries postgres+redis only; the
orchestrator is multi-homed (default + data). Spawned agents and their
sandbox sidecars stay on roboco_default and can no longer resolve or
reach roboco-postgres:5432 / roboco-redis:6379 (redis has no auth —
membership is its only containment). Normal bridge, so host-published
ports (15432/16379) keep working. Applied to both build composes and
the registry compose; docker-compose.yml re-synced byte-identical with
docker-compose.yaml (it had drifted by the sandbox flag block).

ROBOCO_DB_NETWORK_ISOLATED (config default false, armed alongside the
topology) suppresses the legacy _append_gate_env prod-creds injection:
under isolation those creds dead-end, and unreachable creds are worse
than none. DB-needing projects opt into sandbox_services instead. The
flag is deliberately not a panel feature flag - it must travel with the
compose networks: stanzas.

Preserved by construction: agent<->agent A2A and orchestrator->agent SDK
polls on :9000, MCP->orchestrator on :8000, ollama reachability, docker
exec/inspect (daemon socket), host port publishing.

* feat(panel): full mobile responsiveness pass

Shared primitives: useIsMobile (useSyncExternalStore, hydration-safe,
memoized matchMedia subscribe), ResponsiveTable table->card switch below
md (single subtree mounted, no duplicated interactive rows), scrollable
snap TabsList in the base primitive (justify-center-safe so the first
tab stays reachable on overflow), persistent md:hidden bottom tab bar
(Overview/Tasks/Kanban/Chat, safe-area padded).

Applied: card lists for tasks/projects/products/work-sessions/sessions
+ the three raw metrics tables; CEO approval queue / release proposal /
playbook review action rows stack on narrow; command-center reorders
approvals above the fold on mobile; task-header metadata wraps;
Communications + A2A become URL-driven single-pane drill-downs below lg
(fixes the unconstrained-height ScrollArea bug) with dvh heights;
recharts label density/radius adapts via useIsMobile; git diff viewer
gets mobile font + wrap toggle; vh->dvh sweep; chat composers get
safe-area-inset padding; dashboard main p-4 md:p-6 + pb-20 for the bar.

Verified at 375px on the built app: bottom bar, drawer, approval-first
overview, swipeable kanban tab strip. All gates green (eslint, tsc,
vitest 249, next build 24/24 routes).

* feat(auth): cloud auth via FastAPI Users (default-off, single-user cookie session)

ROBOCO_CLOUD_AUTH_ENABLED (default off) lets the panel/API be exposed
beyond localhost without changing the CEO's local no-login flow while
off — get_agent_context and the WS gate are byte-for-byte unchanged in
off-mode. On: header-trust dies for humans — any agent-role claim (ceo
or a privileged PM/board role) with no valid HMAC token or session
cookie is 401, closing the header-spoof hole on the host-published
:8000 port for every role. The agent-fleet HMAC path and the system
self-PATCH keep working unmodified in both modes.

Single seeded CEO user (migration 058 users table, UserTable), no
registration router — idempotent env-driven upsert at startup by PK.
Cookie transport (httponly/secure/samesite=lax) + a JWTStrategy bound
to a fingerprint of the current password hash (rotating the password
invalidates every prior session). Sliding 30-day session: every
authenticated request re-mints the cookie, so an active session never
expires — no unexpected logouts.

Panel: (auth)/login page + proxy.ts (Next 16 rename of middleware; probes
/auth/status over the docker-internal URL, fails open to off) gate the
dashboard; client.ts gets withCredentials + 401->/login. nginx unchanged.

Review hardening: broadened the on-mode rejection from ceo-only to every
non-CEO role without a valid token (was only closed when
ROBOCO_AGENT_AUTH_REQUIRED was also armed); Next-16 proxy.ts rename to
clear the middleware deprecation warning.

* feat(x): RoboCo X account engine — HoM drafts, per-post CEO approval (default-off)

ROBOCO_X_ENGINE_ENABLED (default off, inert without creds). Mirrors the
ReleaseManagerEngine held-artifact shape: XEngine drafts a post when a
release publishes (via a draft_release_post seam on ReleaseProposalService
.approve) and drafts replies to meaningful mentions (dedicated poll loop,
x_seen_mentions dedup ledger, per-cycle/open caps). Drafting is
local-model-only, clamped to 280 chars. Nothing auto-posts — every tweet
is a held task (source x_post/x_reply, confirmed_by_human=False,
Secretary-owned, dispatcher-skipped) the CEO edits/approves/rejects in a
panel queue.

The four OAuth 1.0a secrets live Fernet-encrypted in a singleton
x_credentials row (migration 059, all-or-nothing, API returns only
has_credentials); decryption is server-side, agents never hold creds or
egress. Hand-rolled OAuth 1.0a HMAC-SHA1 signer, no new dependency;
NullXClient makes the unconfigured path a graceful no-op.

XPostService.approve (CEO-only) is the sole caller of post_tweet.

Review hardening: closed a double-post race — the approve path now
re-reads committed task state inside the Redis lock and commits COMPLETED
before releasing, so a concurrent approve that acquires the lock after the
winner released can't re-post (SET-NX is non-waiting, and the route-level
commit landed after the lock dropped). Added a regression test.

* feat(roadmap): board roadmap engine — PO proposes themed cycles, CEO approves per-item (default-off)

ROBOCO_ROADMAP_ENGINE_ENABLED (default off). Weekly, RoadmapEngine opens
ONE held exploration task (source=board_roadmap, confirmed_by_human=False,
Product-Owner-assigned), deduped to one open cycle. A dedicated one-shot
_dispatch_roadmap_exploration spawns the PO solo (not the two-reviewer
board path, which would also spawn HoM + fire Approve-&-Start). The PO
explores read-only (git/KB/metrics/releases/charter/web) and makes one
propose_roadmap call (PO-only content verb) authoring a themed cycle —
goal + 3-7 item drafts — persisted as a roadmap_cycle marker (no table,
no migration; head stays 059).

The CEO acts per-item in the panel roadmap queue: approve materializes a
BACKLOG task (source=roadmap, no assignee — never auto-starts), reject
records a reason; all-items-terminal completes the exploration task.
RoadmapService is idempotent per item. Dispatchers skip board_roadmap.

Includes a real SQLAlchemy dirty-check fix (deep-copy the JSON marker
before mutating, or the in-place edit + reassign compares equal to its
own baseline and the UPDATE is skipped).

Review hardening: create_task_from_draft now honors a draft-declared
source only from a {prompter, roadmap} whitelist — drafts are
LLM-authored, so an unbounded source could impersonate a privileged
origin (release_manager would even wedge that engine's dedup).

* chore(release): 0.17.0

Wave 3 — six default-off subsystems: sandboxed dev DB/Redis, prod
Postgres/Redis network isolation, full mobile UI pass, cloud auth
(FastAPI Users), the RoboCo X account engine, and the board roadmap
engine. Plus the waves 1+2 work already on master since 0.16.0.

Version bumped across the canonical set (config.py, __init__.py,
pyproject.toml, panel/package.json, uv.lock); CHANGELOG [Unreleased]
cut to [0.17.0]; docs/map delta added.

Compose: every optional feature armed :-true in the NAS composes, OFF
in the user-facing registry compose. Two opt-in exceptions default off
(CLOUD_AUTH — needs email/password/secret + TLS, would otherwise fail
startup; ROUTING_STRICT — fail-closed spawning). DB_NETWORK_ISOLATED
stays on in both (coupled to the roboco_data topology).

* chore(compose): arm cloud_auth + routing_strict ON in the NAS composes

Every feature defaults ON in the NAS composes per policy — these two
were wrongly left off. Both keep the ${VAR:-true} form so the operator
controls the real runtime via .env: cloud auth needs
ROBOCO_CLOUD_AUTH_EMAIL/_PASSWORD/_SECRET + TLS set there before a boot
(else startup fails loud), and routing_strict is fail-closed. Registry
compose keeps both off.

* fix(ci): reflow board.md prose (quality gate) + document v0.17.0 env creds

The roadmap section added hard-wrapped prose that failed the markdown
prose gate; reflowed (token-invariant). Also brought .env.example
current: cloud auth (now armed — needs SECRET or startup fails), routing
strict, the X engine (panel-entered OAuth), and web research.

* fix(ci): reduce cyclomatic complexity of five wave-3 blocks (xenon gate)

The wave-3 subagents introduced C-rank functions the CI xenon gate
rejects (my per-item reviews ran ruff/mypy/pytest but not xenon):
- sandbox.janitor_sweep -> extract _list_labeled_sandboxes /
  _list_live_agent_containers / _prune_grace
- x_client.fetch_mentions -> extract _parse_mention_items
- x_engine.run_cycle -> extract _process_mentions
- orchestrator._dispatch_pm_work -> extract the source-skip into a
  MODULE-level _is_held_ceo_source (module, not method, so the
  wholesale-mocked dispatcher unit tests exercise the real logic)
- auth/seed.ensure_seed_user -> extract _apply_seed_updates (module avg -> A)

Behavior-preserving; full suite green (11902), xenon clean.

* fix(ci): declare pyjwt + fastapi-users-db-sqlalchemy as direct deps (deptry)

The cloud-auth code imports jwt and fastapi_users_db_sqlalchemy directly
but they were only transitive deps (via fastapi-users), which deptry
(quality gate, DEP003) rejects. Declared explicitly; deptry roboco/ clean.
Missed originally because local make quality stopped at earlier gates
before reaching deptry.

* feat(x): gate mention replies behind ROBOCO_X_REPLIES_ENABLED (default off)

Per CEO decision: the X engine should only post about releases by
default. Reading mentions needs a paid X API tier, so the mention-reply
half is now a deliberate opt-in on top of release posting.

New default-off flag x_replies_enabled gates the mentions poll loop
(_x_mentions_poll_loop) and XEngine.run_cycle; release-post drafting
(the release-proposal approve hook) is unaffected and still runs when
x_engine_enabled + credentials are set. Added to FEATURE_FLAGS + the
panel card. Tests: release posting works with replies off; run_cycle +
the poll loop are no-ops with replies off.

* fix: 401 only redirects to /login when cloud auth is on; panel-token strips .env quotes

Two bugs that together dead-ended login in secure mode:
- client.ts redirected to /login on ANY 401, so a mismatched panel
  token (header-trust/secure mode, cloud auth off) bounced the user to a
  login page whose backend route isn't mounted -> 404. Now it probes
  /auth/status (bare fetch, no interceptor re-entry) and only redirects
  when cloud_auth_enabled.
- make panel-token read the .env secret with grep|cut without stripping
  surrounding quotes, so a quoted ROBOCO_AGENT_AUTH_SECRET produced a
  token signed with the quotes included — which never verifies against
  the orchestrator (docker-compose/pydantic unquote the secret). Now
  strips surrounding single/double quotes.

* fix: git-log 500 on '|' in commit message; X queue shows an empty state

- GET /api/git/log 500'd (ValueError: Invalid isoformat) when a commit
  SUBJECT contained a '|' (e.g. the 'curl|sh' lockdown commit): the
  fixed '|' field delimiter let the subject's pipe shift the split so
  author+date collapsed into one field. Switched to \x1f (Unit
  Separator), which can't appear in commit content. Regression test with
  a piped subject.
- The X Post Queue returned null when empty, so there was no visible
  place for the X drafts. It now renders a discoverable empty state
  pointing at Settings -> X credentials.

* docs: bring docs/rag + docs/map current for v0.17.0 (waves 1-3)

Agent-facing RAG corpus and codebase map updated for every feature in
the 0.17.0 span, code-verified:
- wave 3: sandbox DB, DB network isolation, cloud auth, X engine
  (+ x_replies_enabled sub-flag), board roadmap engine — new RAG
  architecture pages + role/tool/config-reference updates; new symbols,
  migrations 057-059, panel surfaces, and the get_agent_context
  dual-path across the map slices.
- waves 1-2: A2A live view + switchboard, prompter memory
  (search_past_tasks), Secretary edit access + PM-lighter scope, the
  PR-gate auto-submit turn cut (ROBOCO_PR_GATE_AUTO_SUBMIT_ENABLED).
- correctness fix: api-routes-schemas.md no longer claims the A2A admin
  routes are reachable by any authenticated agent — they carry a
  _require_ceo gate (wave 2c).

docs/internal, _front.md deltas, and the frozen _complete_map.md
snapshot untouched.

* fix(rag): atomic upsert for indexed-doc tracking (kills e2e segfault)

The indexed-document tracking write used check-then-insert in two paths
(IndexedDocumentRepository.upsert_batch and the file-source
_upsert_doc_record). Under concurrent indexing both callers saw no row
and both inserted, so the second violated uq_indexed_doc_source and
poisoned its transaction — surfacing in CI as the intermittent
_checkin_failed SIGSEGV on the failed connection's pool checkin.

Both paths now use INSERT ... ON CONFLICT DO UPDATE against the
constraint: coalesce keeps an existing title/preview when the new value
is empty (matching the old guards) and metadata is jsonb-merged. The
batch dedupes within itself first (ON CONFLICT can't touch a row twice
in one statement). expire_all after the Core upsert keeps same-session
ORM reads consistent with the merged DB row.

---------

Co-authored-by: Renn F <rennf93@users.noreply.github.com>
2026-07-03 19:24:00 +02:00
2026-06-07 02:53:51 +02:00
2026-05-05 03:19:43 +02:00

RoboCo

AI Agents Company - A virtual organization of 25 AI agents + 1 human CEO, designed to operate as a complete software development workforce.

Watch the 26-minute RoboCo intro on YouTube — what it is, a walkthrough, and how to use it
Watch the 26-min intro
what it is, a walkthrough, and how to use it
Watch the 2.5-hour Working with RoboCo build session on YouTube — taking a conversation all the way to a shipped feature
Watch the 2.5-hour build session
a conversation → a shipped feature

Twelve-second looping preview of the RoboCo control panel — the org tree, a task in progress, and an approval queue.
Watch the full 2:33 walkthrough (.mp4) →

Warning

RoboCo is early-stage, work-in-progress software (v0). It's under active development, runs in a homelab, and will have rough edges, breaking changes, and bugs. It is not production-ready and the API/database schema are not stable yet. Treat it as a working prototype to explore and build on — please don't expose it to the public internet as-is. Issues and PRs very welcome.

Tip

📚 Full documentation: docs.roboco.tech — install & first run, the company model, a page-by-page panel reference, model providers, the optional subsystems, deployment, and the API.

Overview

RoboCo implements a structured organizational hierarchy with formal communication protocols, task management, and quality controls. The system enables a single human (CEO) to orchestrate complex multi-project development at scale.

CEO (You, the human)
    │
    ├── Intake (on-demand interviewer: chats only with you to draft a task)
    ├── Secretary (on-demand chief-of-staff: reads company state, runs gated directives)
    ├── PR Reviewer (read-only main reviewer: inbound external/fork + internal PRs, and the root→master in-path gate)
    │
    └── Board (3 agents)
         ├── Product Owner
         ├── Head of Marketing
         └── Auditor (silent observer, reports to you)
              │
              └── Main PM (coordinates all cells)
                   │
                   ├── Backend Cell (6 agents: 2 Devs, 1 QA, 1 PM, 1 Documenter, 1 PR Reviewer)
                   ├── Frontend Cell (6 agents: 2 Devs, 1 QA, 1 PM, 1 Documenter, 1 PR Reviewer)
                   └── UX/UI Cell (6 agents: 2 Devs, 1 QA, 1 PM, 1 Documenter, 1 PR Reviewer)

The 25 agents = Intake + Secretary + PR Reviewer + the Board (3) + Main PM + the three 6-agent cells (18). Agents run on Anthropic Claude by default, or on xAI Grok (the official grok CLI on a SuperGrok subscription) — see the provider note under Configuration.

How it works

You hand a task to the company; it runs through a real build → review → document → merge pipeline and comes back to you to approve.

One full loop, put simply:

  1. You give the Board a task — they review it. The Product Owner and Head of Marketing turn your ask into requirements and acceptance criteria.
  2. You approve — the Main PM starts the work. A notification asks for your Approve & Start decision; approve, and the Main PM breaks it into per-cell subtasks.
  3. Each cell's PM delegates, supports, and triages its developers (UX/UI, Frontend, Backend).
  4. Developers build it, QA verifies and gates it, Documenters keep the books.
  5. Cell PMs merge their PRs into the Main PM's branch.
  6. The Main PM opens the final PR and notifies you "It's done!" — you approve and merge, or send it back for rework. (Only you ever merge to master.)

— Full circle —

See the full walkthrough, with screenshots →

Or watch the full panel walkthrough (video) →

Project Structure

roboco/
├── roboco/                      # Main Python package
│   ├── api/                     # FastAPI routes & schemas
│   │   ├── routes/              # API endpoints (tasks, git, agents, etc.)
│   │   └── schemas/             # Pydantic request/response models
│   ├── services/                # Business logic services
│   │   ├── task.py              # Task lifecycle management
│   │   ├── workspace.py         # Multi-agent workspace management
│   │   ├── messaging.py         # Agent communication
│   │   └── optimal.py           # RAG/Knowledge base (in-house pgvector)
│   ├── models/                  # Pydantic domain models
│   ├── db/                      # SQLAlchemy ORM & session
│   ├── enforcement/             # Task lifecycle state machine
│   ├── runtime/                 # Orchestrator for agent spawning
│   ├── agents/                  # Agent base classes
│   ├── mcp/                     # MCP server implementations
│   └── config.py                # Application configuration
├── agents/
│   └── prompts/                 # Agent system prompts (roles, teams, identities)
├── docs/
│   ├── rag/                     # Agent knowledge base (indexed into RAG)
│   └── map/                     # Exhaustive codebase map (agent-facing)
├── alembic/                     # Database migrations
├── CLAUDE.md                    # Claude Code guidance
├── docker-compose.yml           # Full stack, built from source
└── docker-compose.registry.yml  # Full stack, pulled from the image registry

Running RoboCo

You need Docker + Docker Compose and a Claude Code auth directory on the host (~/.claude, mounted into the orchestrator so agents can reach the model). Copy .env.example to .env and set at least ROBOCO_ENCRYPTION_KEY and ROBOCO_AGENT_AUTH_SECRET (that file shows how to generate each). However you start it, the whole company is reachable at one origin: http://localhost:3000.

Optional — run agents on xAI Grok instead of Claude. RoboCo can spawn agents on xAI's official grok CLI authenticated by a SuperGrok subscription (no metered API key). Run grok login once on the host and point ROBOCO_HOST_GROK_DIR at the resulting ~/.grok so it mounts into Grok agents; the orchestrator keeps the ~6h token refreshed for you. See the Grok block in .env.example (ROBOCO_HOST_GROK_DIR, ROBOCO_GROK_AGENT_IMAGE, ROBOCO_GROK_CLI_MODEL, ROBOCO_GROK_REASONING_EFFORT).

Option 1 — Run the pre-built images (quickest)

Every release publishes all RoboCo images to both the GitHub Container Registry and Docker Hub, so you can run the full stack without building anything. Use the registry compose:

git clone https://github.com/rennf93/roboco.git && cd roboco
cp .env.example .env                                   # then edit in your secrets
docker compose -f docker-compose.registry.yml pull
docker compose -f docker-compose.registry.yml up -d

Choose the registry and version with two env vars (defaults shown):

ROBOCO_REGISTRY=ghcr.io/rennf93   # or docker.io/renzof93
ROBOCO_VERSION=latest             # or a pinned release, e.g. 0.15.0

The orchestrator spawns the matching pre-built agent images on demand — no build toolchain or source compile on your host.

Option 2 — Build from source

The same full stack, built locally from the Dockerfiles instead of pulled:

git clone https://github.com/rennf93/roboco.git && cd roboco
cp .env.example .env              # then edit in your secrets
docker compose up -d              # builds images on first run, then starts everything

Option 3 — Local development (no full stack)

For hacking on the code itself, run only the backing services in Docker and the API on your host. RoboCo's own code requires Python 3.13+ (uv will fetch it if needed):

uv sync
docker compose up -d postgres redis ollama   # backing services only
uv run alembic upgrade head                   # migrate the database
uv run python -m roboco.cli                   # API + orchestrator

# Or just the API without the orchestrator:
uv run uvicorn roboco.api.app:app --reload --host 0.0.0.0 --port 8000

Configuration

Key environment variables (see roboco/config.py for all options):

# API Server
ROBOCO_HOST=0.0.0.0
ROBOCO_PORT=8000

# Database
ROBOCO_DATABASE_HOST=localhost
ROBOCO_DATABASE_PORT=5432
ROBOCO_DATABASE_NAME=roboco

# Workspaces (Multi-Agent Git)
ROBOCO_WORKSPACES_ROOT=/data/workspaces
ROBOCO_WORKSPACE_AUTO_CLONE=true

# RAG/LLM
ROBOCO_LOCAL_LLM_BASE_URL=http://roboco-ollama:11434/v1
ROBOCO_LOCAL_LLM_MODEL=glm-5.2:cloud

# Feature flags (default-off unless noted; toggle from Settings → Feature Flags)
ROBOCO_CONVENTIONS_ENABLED=false        # per-project architectural conventions standard
ROBOCO_TOOLCHAIN_MATCH_ENABLED=false    # build each target project under its own Python
ROBOCO_OVERLOAD_BREAK_ENABLED=true      # park a provider on a persistent model-API overload

Multi-Agent Workspace Structure

Each agent gets their own git clone for parallel development:

{ROBOCO_WORKSPACES_ROOT}/
└── {project-slug}/
    └── {team}/
        └── {agent-slug}/
            └── [git repository]

Example:
/data/workspaces/roboco/backend/be-dev-1/
/data/workspaces/roboco/backend/be-dev-2/

Task Lifecycle

backlog → pending → claimed → in_progress → verifying → awaiting_qa
    ↓                              ↓              ↓           ↓
cancelled                      blocked      needs_revision   awaiting_documentation
                               paused                              ↓
                                                           awaiting_pm_review
                                                                   ↓
                                                           awaiting_ceo_approval
                                                                   ↓
                                                              completed

Assembled, PR-bearing tasks pass through one extra stage — the in-path PR-review gate — before the PM merges:

in_progress → awaiting_pr_review → awaiting_pm_review
   (submit_up /      (pr_pass)
    submit_root)     (pr_fail → needs_revision)

The cell PM's submit_up (cell→root PR) and the Main PM's submit_root (root→master PR) open the assembled PR and enter the gate; a PR reviewer pr_passes it on to the PM merge or pr_fails it back. Leaf dev tasks (reviewed by QA) and branchless coordination roots skip the gate.

API Endpoints

Domain routes are mounted under /api:

Route Group Description
/api/tasks Task CRUD, lifecycle, claiming
/api/agents Agent management
/api/git Git operations (status, commit, push, PR)
/api/sessions Communication sessions
/api/messages Agent messages
/api/projects Project (repo) management
/api/work-sessions Git work session tracking
/api/optimal RAG/Knowledge base queries
/api/journals Agent journals/reflections
/api/orchestrator/status Orchestrator / dispatcher status

The agent gateway verbs are served separately under /api/v1/flow/{role}/{verb} (intent verbs) and /api/v1/do (content tools) — see the Agent Gateway.

Development

# Install dev dependencies
uv sync --all-extras

# Run tests
uv run pytest

# Format and lint
uv run ruff format .
uv run ruff check .
uv run mypy roboco/

# Type checking
uv run mypy roboco/

Core Principles

  1. Everything is a task - All work is tracked and documented
  2. No work without a task - Create task record first
  3. No task without acceptance criteria - How do we know it's done?
  4. No closure without documentation - Future agents need context
  5. Communication is constant - Stream reasoning, log everything
  6. The Auditor sees all - Quality monitored silently
  7. CEO approves major changes - Human-in-the-loop for critical decisions

Technology Stack

Layer Technology
API Framework FastAPI
Database PostgreSQL + SQLAlchemy (async)
Vector Store PostgreSQL + pgvector (in-house engine)
Cache/Queue Redis
RAG Engine in-house (asyncpg + pgvector, hybrid retrieval)
Embeddings qwen3-embedding:0.6b (Ollama)
Local LLM Ollama (glm-5.2:cloud)
Cloud LLM Claude API (Anthropic) + xAI Grok (official grok CLI, SuperGrok subscription)
Package Manager uv

Status

Core Infrastructure (Complete)

  • Data models (Pydantic)
  • Database ORM (SQLAlchemy async)
  • Task lifecycle state machine
  • Multi-agent workspace management
  • Agent prompts (25 agents)
  • Messaging API
  • Task API with full lifecycle
  • Git operations API
  • RAG/Knowledge base (in-house pgvector engine)
  • Agent orchestrator
  • CEO approval workflow
  • Pluggable agent providers (Claude Code + xAI Grok on the official grok CLI)
  • Inbound PR review (read-only PR-reviewer + CEO supersede/dismiss queue)
  • Self-healing CI loop for RoboCo's own repo (default-off, CEO-gated)
  • Business Goals tab with a live Company Scorecard (delivery, spend-vs-budget, lead time)

In Progress

  • Frontend panel (vendored under panel/, served through nginx on :3000)
  • Full agent autonomy testing

Security

Important

Do not expose RoboCo to the public internet as-is. It is designed to run on a trusted private network (homelab / LAN).

Agent authentication. Requests identify the caller with X-Agent-Id / X-Agent-Role headers. The orchestrator issues each spawned agent an HMAC token (X-Agent-Token, signed with ROBOCO_AGENT_AUTH_SECRET) that binds its id, role and team. Token enforcement is gated by ROBOCO_AGENT_AUTH_REQUIRED:

  • ROBOCO_AGENT_AUTH_REQUIRED unset/false (default): header-trust mode — the role headers are accepted without a token, so any client that can reach the API may claim any role (including ceo). The API logs a warning at startup in this mode. Acceptable only on a trusted network.
  • ROBOCO_AGENT_AUTH_REQUIRED=true: every request must carry a valid token; an agent cannot spoof another agent's role. The control panel keeps working because nginx — the only trusted hop between the browser and the API — injects the CEO token (X-Agent-Token) on /api and /ws, so the browser never holds the signing secret. Generate that token with make panel-token and set it as ROBOCO_PANEL_AGENT_TOKEN in .env before enabling secure mode.

WebSocket streams. Token enforcement is currently REST-only. The /ws/* endpoints authenticate by agent_id query param at most and do not yet validate X-Agent-Token, even in secure mode — nginx injects the token so the panel works, but a direct WebSocket connection that bypasses nginx is not rejected. In particular the operator stream /ws/system (rate-limit lifecycle + token-usage snapshots for the dashboard) is unauthenticated. These streams are read-only — no control surface, secrets, or task content — but treat the orchestrator port as trusted-network-only until WebSocket auth lands.

Secrets (the Fernet ROBOCO_ENCRYPTION_KEY, GitHub PATs) live encrypted in the database and in gitignored env files — never in the repo. Per-project git tokens are Fernet-encrypted at rest and never returned by the API.

License

Copyright (c) 2026 Renzo Franceschini

RoboCo is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0). See LICENSE for the full text.

The AGPL's network-use clause (section 13) means that if you run a modified version of RoboCo as a network service, you must make your modified source available to its users. This keeps the project open while preventing closed, hosted re-distributions.

Contributing

Contributions are welcome. All contributors must sign the Contributor License Agreement (CLA.md) — this is automated on your first pull request. See CONTRIBUTING.md for the workflow and why the CLA exists.

S
Description
No description provided
Readme AGPL-3.0
100 MiB
Languages
Python 80.8%
TypeScript 17%
HTML 0.8%
Shell 0.6%
JavaScript 0.3%
Other 0.5%