547fe444f2 [4865ff8b] Add WebSocket support to the usage dashboard (#115)
* [e7349d84] feat(dashboard): WS usage store, hook extension, status badge, and smooth animations (#111) (#113)

- Add src/store/usage-store.ts with typed UsageData interface, useUsageStore
  Zustand store, setUsageData, clearUsageData, and setWsState actions
- Export useUsageStore and UsageData from store/index.ts
- Extend use-rate-limit-websocket.ts: rename msg type to SystemWsMessage,
  add key_metrics field; add useEffect syncing wsState into useUsageStore;
  add USAGE_UPDATE/USAGE_SNAPSHOT handler dispatching to useUsageStore
  (RATE_LIMIT_HIT/LIFTED handling and onReconnect unchanged)
- Update CommandCenter to read key_metrics from useUsageStore when
  wsState === 'connected' and usageData non-null; falls back to
  useCeoOverview() (refetchInterval: 60000) when WS disconnected
- Update KeyMetricsPanel: add wsState prop, render connection status Badge
  matching AgentStreamViewer pattern (bg-green-500+Wifi / bg-yellow-500+
  Loader2 spin / bg-gray-500+WifiOff); add transition-all duration-300
  ease-in-out to metric value spans for smooth animated updates

Co-authored-by: Frontend Developer 1 <fe-dev-1@agents.roboco.dev>

* [c9745ee8] feat(events): add USAGE_UPDATE/SNAPSHOT event types, throttled publisher, /ws/system usage bridge (#112) (#114)

- Add EventType.USAGE_UPDATE='usage.update' and EventType.USAGE_SNAPSHOT='usage.snapshot'
  to the EventType StrEnum in roboco/models/events.py

- Create roboco/services/usage_events.py with _UsageThrottle class (5-second per-agent
  window using time.monotonic()) and publish_usage_update() / publish_usage_snapshot()
  helpers; lazy imports prevent circular dependency with roboco.events

- Extend orchestrator._sweep_token_snapshots() to publish USAGE_UPDATE per active agent
  (throttled) and a USAGE_SNAPSHOT aggregate after each sweep cycle; wrapped in
  contextlib.suppress so event errors never abort DB snapshot operations

- Add _handle_usage_event() to websocket_bridge.py following _handle_rate_limit_event
  pattern; register USAGE_UPDATE and USAGE_SNAPSHOT subscriptions in
  register_websocket_bridge_handlers() forwarding both to /ws/system via broadcast_system()

- Add unit tests: test_usage_events.py (throttle suppression, publish helpers) and
  test_websocket_bridge.py extended with _handle_usage_event coverage and updated
  registration assertion to include USAGE_UPDATE/USAGE_SNAPSHOT

Co-authored-by: Backend Developer 1 <be-dev-1@agents.roboco.dev>

* fix(usage-ws): reconcile the realtime token/cost contract end-to-end

The backend and frontend halves shipped mismatched contracts, so the usage
dashboard never received live data:

- The bridge forwarded the dotted event value ("usage.update") while the panel
  switched on "USAGE_UPDATE"; map both to the UPPER_SNAKE type string the same
  way the rate-limit handler does.
- The backend emitted token/cost telemetry but the frontend read a key_metrics
  field and fed the org-metrics panel. Rewire the frontend to consume the
  USAGE_SNAPSHOT token/cost payload into the "Token Usage & Cost" panel —
  WS-first with polling fallback and a connection-status badge — and revert the
  unrelated KeyMetricsPanel / CommandCenter wiring.

Backend cleanups in the same path:

- Replace the multi-argument publish helpers with typed UsageUpdate /
  UsageSnapshot payloads, removing the too-many-arguments lint suppressions.
- Extract _fetch_agent_tokens and _persist_token_snapshot from the token sweep,
  removing the too-many-statements suppression; label the live snapshot "live".

Hardening uncovered while fixing the above:

- _finalize_spawn_session pulled the full RAG stack into the
  session-finalization path through a transcript-parse import; move the pure
  parser into a dependency-light roboco.agent_sdk.transcript_usage module so
  finalization never imports the agent SDK server.
- Reduce _finalize_spawn_session complexity by extracting
  _resolve_final_token_usage, and widen the transcript-fallback guard so a read
  error can never abort finalization.

Also align KeyMetricsPanel with the metrics /dashboard/ceo actually returns: it
read velocity_24h / avg_time_to_done / active_agents, none of which
get_key_metrics() emits, so four of five rows rendered "—". Render
velocity_weekly, completion_rate, documentation_coverage and active_blockers.

* docs: note live usage push over /ws/system on the usage dashboard

* fix(usage): finalize on self-exit and de-duplicate transcript token counts

Two bugs left token capture broken even after the transcript-read fallback
landed — surfaced by a live agent run:

- Agents that self-exit (the normal i_am_idle -> container shutdown, exit 0)
  were never finalized. _finalize_spawn_session is only called from
  stop_agent(), but a graceful self-exit goes through _handle_stopped_container,
  which set the instance OFFLINE and returned without finalizing — leaving the
  spawn-session row open with zero tokens. Finalize there for both graceful
  (exit_reason="completed") and crash (exit_reason="crashed") exits.

- sum_transcript_usage double-counted. Claude Code logs one assistant message
  as several JSONL lines (one per content block — thinking / text / tool_use),
  each repeating the same message.usage, so summing every line roughly doubled
  the totals. De-duplicate by message.id.

Verified against a live agent transcript: the raw sum (12, 1068, 62502, 115828)
vs the de-duped (6, 516, 62502, 63336), which matches the session's
authoritative result.usage exactly.

* feat(usage): fall back to the transcript in the live token sweep

The 60s token sweep read only the agent SDK's /usage/status, which races
container teardown and reports zero mid-run — so live usage (and the
USAGE_SNAPSHOT pushed to /ws/system) stayed at zero for active agents.
Extract _resolve_active_tokens: try the SDK, then fall back to the durable
transcript (the same source finalize uses) so running agents report live.

* feat(usage): add GET /usage/sessions for the dashboard's Recent Sessions

The panel's Recent Sessions table was mock-only — the backend had no sessions
endpoint, so production always showed 'No sessions recorded yet'. Add
UsageService.get_recent_sessions + a /usage/sessions route returning the most
recent spawn-session rows (token totals + cost), and point the panel client
at it.

---------

Co-authored-by: Frontend Developer 1 <fe-dev-1@agents.roboco.dev>
Co-authored-by: Backend Developer 1 <be-dev-1@agents.roboco.dev>
Co-authored-by: Renn F <rennf93@users.noreply.github.com>
2026-06-11 23:19:50 +02:00
2026-06-07 02:53:51 +02:00
2025-12-10 02:49:54 +01:00
2026-06-04 16:34:30 +02:00
2026-06-09 17:08:34 +02:00
2026-06-09 17:08:34 +02:00
2026-05-05 03:19:43 +02:00

RoboCo

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

RoboCo control panel: the task tree for a feature, showing Board → Main PM → Backend / Frontend / UX/UI cells → developer subtasks, with live lifecycle statuses (completed, in progress, awaiting PM review, paused) and real GitHub PRs (#59–#62).

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.

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)
    │
    └── Board (3 agents)
         ├── Product Owner
         ├── Head of Marketing
         └── Auditor (silent observer, reports to you)
              │
              └── Main PM (coordinates all cells)
                   │
                   ├── Backend Cell (5 agents: 2 Devs, 1 QA, 1 PM, 1 Documenter)
                   ├── Frontend Cell (5 agents: 2 Devs, 1 QA, 1 PM, 1 Documenter)
                   └── UX/UI Cell (5 agents: 2 Devs, 1 QA, 1 PM, 1 Documenter)

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_brain/       # RAG/Knowledge base (piragi)
│   ├── models/                  # Pydantic domain models
│   ├── db/                      # SQLAlchemy ORM & migrations
│   ├── 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/
│   ├── how-to.md               # Visual walkthrough of the workflow
│   └── rag/                     # Agent knowledge base (indexed into RAG)
├── alembic/                     # Database migrations
├── CLAUDE.md                    # Claude Code guidance
└── docker-compose.yml           # Local development stack

Quick Start

# Install dependencies
uv sync

# Start PostgreSQL and Redis (Docker)
docker compose up -d

# Run database migrations
uv run alembic upgrade head

# Start the API server
uv run python -m roboco.cli

# Or just the API without 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:cloud

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

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 pgvector (via piragi)
Cache/Queue Redis
RAG Library piragi
Embeddings qwen3-embedding:0.6b (sentence-transformers)
Local LLM Ollama (glm-5:cloud)
Cloud LLM Claude API (Anthropic)
Package Manager uv

Status

Core Infrastructure (Complete)

  • Data models (Pydantic)
  • Database ORM (SQLAlchemy async)
  • Task lifecycle state machine
  • Multi-agent workspace management
  • Agent prompts (20 agents)
  • Messaging API
  • Task API with full lifecycle
  • Git operations API
  • RAG/Knowledge base (piragi + pgvector)
  • Agent orchestrator
  • CEO approval workflow

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.

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%