mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
docs: add the user-facing MkDocs documentation site
Build a complete user-facing documentation site (MkDocs Material) under docs/, served at roboco.dev/docs via a new gh-pages deploy workflow. - Sections: Get Started, The Company, the Tour, Operating the Panel, Choosing & Running Models, Cost & Observability, Optional Subsystems, Configure & Deploy, API Reference, Troubleshooting & Security (55 pages). - mkdocs.yml (Material theme; excludes the agent-facing rag/ corpus, internal scratch, and orphaned stub trees) and .github/workflows/docs.yml (mkdocs gh-deploy to gh-pages). - Retire the stale root usage.md and deployment.md to redirect stubs into the site. - Fix the docs tooling: add the pymarkdownlnt dependency + .pymarkdown.json, run serve-docs/lint-docs/fix-docs under the docs extra, add a build-docs strict gate. - Fix the roboco console-script entry point (cli, not the un-awaited async main). - README: correct the project-structure tree (optimal.py, alembic) and link the docs site.
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
# Run on xAI Grok
|
||||
|
||||
RoboCo can run the entire workforce — or just some agents — on **xAI Grok**, using xAI's official `grok` CLI on a **SuperGrok subscription** rather than a metered API key. That matters operationally: a subscription can't run out of credits mid-task, so a Grok fleet won't stall halfway through a delivery the way a metered key can. Grok reaches full parity with the Claude path by construction: the same MCP gateway, the same per-role tool manifest, the same prompt-injection and bash guards, the same per-agent cost capture.
|
||||
|
||||
## Set it up once
|
||||
|
||||
Authenticate Grok on the host with the official CLI, then point RoboCo at the resulting directory:
|
||||
|
||||
```bash
|
||||
grok login # once, on the host — creates ~/.grok/auth.json
|
||||
```
|
||||
|
||||
Then in `.env`:
|
||||
|
||||
```bash
|
||||
ROBOCO_HOST_GROK_DIR=/home/youruser/.grok # the REAL host ~/.grok to mount in
|
||||
```
|
||||
|
||||
The orchestrator mounts that directory's `auth.json` **read-only** into each Grok agent container. On a NAS or any docker-in-docker deploy the orchestrator's home is not the host's home, so `ROBOCO_HOST_GROK_DIR` must point at the actual host path where `grok login` wrote `~/.grok` — otherwise agents start with no credential.
|
||||
|
||||
Finally, on **Settings → AI Providers** set the routing mode to **Grok** (whole fleet) or pin individual agents to a Grok model in **Mix** mode. See [Choosing a provider](./provider-routing.md) for the modes and precedence. The [installation guide](../get-started/installation.md#optional-run-on-grok-instead) covers the same first-run steps inline.
|
||||
|
||||
## The token refreshes itself
|
||||
|
||||
The Grok access token has a fixed ~6-hour, server-set lifetime, and the CLI can't refresh it headlessly — on an expired token it would hang forever at an interactive login prompt. RoboCo handles this for you:
|
||||
|
||||
- Once per dispatch tick the orchestrator mints a fresh token from the offline-access refresh token (xAI's OIDC `refresh_token` grant) before expiry and atomically rewrites the shared `auth.json` in place. The refresh fires `ROBOCO_GROK_AUTH_REFRESH_SKEW` seconds (default `1800`) ahead of expiry.
|
||||
- As a backstop, each agent's entrypoint runs `python -m roboco.llm.providers.grok_auth --check` and **refuses to start** on a missing or expired token instead of hanging.
|
||||
|
||||
!!! warning "The orchestrator's `~/.grok` mount must be writable"
|
||||
The orchestrator rewrites `auth.json` when it refreshes the token, so the orchestrator's own mount of `~/.grok` must be **read-write**. (The per-agent mount stays read-only — agents only read the credential.) If the orchestrator can't write it, the token will expire and Grok agents will fail their start-up `--check`.
|
||||
|
||||
## Per-fleet tuning
|
||||
|
||||
Three optional knobs let you trade cost against quality across the whole Grok fleet. All are env-set and apply uniformly (no per-role reduction — that's parity with the Claude path):
|
||||
|
||||
| Variable | Default | What it does |
|
||||
|----------|---------|--------------|
|
||||
| `ROBOCO_GROK_REASONING_EFFORT` | unset (model default) | The `grok --effort` level. Set `low` / `medium` / `high` / `xhigh` / `max` to dial cost vs quality; empty, `default`, or `full` keeps the model's own default. |
|
||||
| `ROBOCO_GROK_MAX_TURNS` | `200` | The per-agent turn cap for a `grok -p` run. |
|
||||
| `ROBOCO_GROK_MAX_COST_USD` | `0` (off) | A per-agent cost ceiling in USD. The grok CLI has no live usage hook, so the orchestrator reads each running container's captured cost and kills it once it crosses this ceiling — a backstop against a runaway loop. `0` disables the cap. |
|
||||
|
||||
Two more variables exist mostly for staged rollouts and tests:
|
||||
|
||||
| Variable | Default | What it does |
|
||||
|----------|---------|--------------|
|
||||
| `ROBOCO_GROK_AGENT_IMAGE` | `roboco-agent-grok:latest` | Override the Grok agent Docker image. |
|
||||
| `ROBOCO_GROK_CLI_MODEL` | `grok-build` | The grok CLI model id passed to agents. |
|
||||
|
||||
!!! note "Usage and cost still show up"
|
||||
Each Grok agent gets a per-agent usage directory mounted read-write so its token/cost is read back when the session finalizes. Grok traffic therefore lands on the same [usage dashboard](../operations/cost-and-usage.md) as Claude, priced from the captured session totals.
|
||||
|
||||
## Next
|
||||
|
||||
- [Choosing a provider](./provider-routing.md) — set the Grok mode or pin agents in Mix.
|
||||
- [What keeps a run alive](./resilience.md) — Grok agents park-and-resume on a rate limit like any other provider.
|
||||
@@ -0,0 +1,25 @@
|
||||
# Choosing & Running Models
|
||||
|
||||
RoboCo's agents are backend-agnostic. By default the whole workforce runs on **Anthropic Claude**, authenticated from the Claude Code session on your host — no API key to manage. You can route the company onto **xAI Grok** instead, or point individual agents and roles at **local / self-hosted** models, all from one page in the panel.
|
||||
|
||||
<div class="grid cards" markdown>
|
||||
|
||||
- **[Provider routing](provider-routing.md)**
|
||||
|
||||
---
|
||||
|
||||
The Settings → AI Providers page: the routing modes, agent-over-role-over-global precedence, saved keys, and the fail-soft fallback.
|
||||
|
||||
- **[Running on Grok](grok.md)**
|
||||
|
||||
---
|
||||
|
||||
The whole workforce on xAI Grok via the official CLI and a SuperGrok subscription — no metered key.
|
||||
|
||||
- **[Resilience](resilience.md)**
|
||||
|
||||
---
|
||||
|
||||
What keeps a run alive: crash auto-retry, and how rate limits and provider overloads park work instead of dropping it.
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,60 @@
|
||||
# Choosing a provider
|
||||
|
||||
By default every agent runs on Anthropic Claude — no key, no config. The orchestrator mounts your host `~/.claude` session into each container and that's the whole setup. When you want something else — the whole fleet on Grok, a few agents on a self-hosted model, or a deliberate mix — you don't edit env files. You set it on **Settings → AI Providers** (`/settings/ai-providers`, linked from the sidebar footer), and the choice is stored server-side and resolved per agent at spawn.
|
||||
|
||||
## The routing modes
|
||||
|
||||
The page has one global **routing mode** that decides which backend every agent uses unless you override it per agent:
|
||||
|
||||
| Mode | What it does | Needs |
|
||||
|------|--------------|-------|
|
||||
| **Anthropic** | Every agent runs on Claude via the mounted `~/.claude` auth. The default. | Nothing — the orchestrator's `~/.claude` mount |
|
||||
| **Grok** | Every agent runs on xAI Grok (`grok-build`). | A saved Grok key *or* a SuperGrok login — see [Run on Grok](./grok.md) |
|
||||
| **Ollama** | Every agent runs on Ollama Cloud. | A saved Ollama Cloud key |
|
||||
| **Self-Hosted** | Every agent runs against your own OpenAI-compatible endpoint. | A base URL with a successful **Test Connection** |
|
||||
| **Mix** | Pin individual agents to specific models; everything else inherits the global default. | Whatever the pinned models need |
|
||||
|
||||
Anthropic, Ollama Cloud, and self-hosted models all speak the Anthropic Messages wire protocol, so they run *through* the same Claude Code runtime — the orchestrator just injects the endpoint and key. Only Grok speaks a different protocol and runs in its own agent image. You don't have to think about that distinction; it's just why Grok is the one mode with a separate setup page.
|
||||
|
||||
!!! note "The CEO seat is not an agent"
|
||||
Mix mode shows a per-agent table mirroring the org chart, but you (the CEO) are intentionally excluded — there's no model to assign to the human seat. The Intake (Prompter) and Secretary chats *are* in the table.
|
||||
|
||||
## How a route is resolved: agent > role > global
|
||||
|
||||
When the orchestrator spawns an agent, it picks the model by a three-rung precedence ladder, most specific first:
|
||||
|
||||
1. **Agent** — a model pinned to that exact agent (set in Mix mode).
|
||||
2. **Role** — a model assigned to the agent's role.
|
||||
3. **Global** — the global mode's default.
|
||||
|
||||
The first rung that has an assignment wins. So in Mix mode you can pin `be-dev-1` to one model, leave the rest of the backend cell on the global default, and the dispatcher resolves each one independently at spawn time. Switching the global mode **clears all per-agent overrides** (the panel asks you to confirm), so flip to Mix *after* you've chosen your baseline, not before.
|
||||
|
||||
## Saving keys and endpoints
|
||||
|
||||
Three secrets live on this page, all stored **Fernet-encrypted** server-side and **never returned by the API** — the panel only ever sees a `has_key` / `has_token` boolean, so you re-enter (you can't read back) a key:
|
||||
|
||||
- **Grok (xAI) key** — only needed if you authenticate Grok with a key rather than a SuperGrok login.
|
||||
- **Ollama Cloud key** — required before any agent can route to Ollama Cloud.
|
||||
- **Self-hosted endpoint** — a base URL plus an optional auth token. Hit **Test Connection** to confirm reachability and auto-discover the model list; **Refresh** re-discovers it. A self-hosted assignment won't save until the connection tests clean.
|
||||
|
||||
The panel guards you client-side: it blocks saving a Grok / Ollama / self-hosted assignment when the matching key or connection is missing, and warns when an Ollama-routed agent has no key (see below).
|
||||
|
||||
## Fail-soft: misconfig falls back to Anthropic
|
||||
|
||||
Routing is deliberately fail-soft. A *stalled* spawn is worse than a *wrong* model, so on any of these the orchestrator silently degrades that agent to Anthropic Claude rather than refusing to start it:
|
||||
|
||||
- no assignment found for the agent, its role, or the global default;
|
||||
- a self-hosted or Ollama endpoint that's unreachable (the orchestrator probes `/api/tags` before committing to it);
|
||||
- a stored key or token that fails to decrypt.
|
||||
|
||||
!!! warning "A quiet fallback can look like success"
|
||||
Because the fallback is silent, an agent you *think* is on your self-hosted model may actually be running on Claude — for example if the endpoint went unreachable after you tested it. The fallback is logged in the orchestrator (`docker compose logs orchestrator` shows the warning). If you're routing away from Anthropic, watch the per-model breakdown on the [usage dashboard](../operations/cost-and-usage.md) to confirm the traffic is landing where you intended.
|
||||
|
||||
!!! info "Providers are seeded by the migrations"
|
||||
The Anthropic, Grok, Ollama Cloud, and self-hosted provider rows are created by `alembic upgrade head`, which the stack runs for you on boot. The AI Providers page only sets keys, mode, and assignments — it never creates providers. If you skipped migrations you'll see "provider not seeded" errors here.
|
||||
|
||||
## Next
|
||||
|
||||
- [Run on Grok](./grok.md) — the SuperGrok path end to end.
|
||||
- [What keeps a run alive](./resilience.md) — crash retry and provider park-and-resume.
|
||||
- The same guardrails apply on every backend — see [how agents are sandboxed](../company/agent-gateway.md).
|
||||
@@ -0,0 +1,43 @@
|
||||
# What keeps a run alive
|
||||
|
||||
A long delivery run spans hundreds of spawned containers, and the things that can interrupt one — a model crash, a provider rate limit, a transient overload — are normal, not exceptional. RoboCo is built so none of those quietly kills the work or burns your tokens crash-looping. Two mechanisms do the heavy lifting: **crash auto-retry then escalate**, and **provider park-and-probe**. Both run server-side in the orchestrator, the same way on every backend.
|
||||
|
||||
## Crash: auto-retry, then escalate once
|
||||
|
||||
When an agent container stops, the orchestrator inspects how it exited:
|
||||
|
||||
- **A clean exit** (the agent called `i_am_idle` — it ran out of work) resets that agent's error count. Nothing to do.
|
||||
- **A provider overload** (see below) parks the provider instead of treating it as a crash.
|
||||
- **A genuine crash** goes to retry-or-escalate.
|
||||
|
||||
On a real crash the orchestrator bumps the agent's error count and **respawns it on the same task** — up to a cap of **3** retries. At exactly the cap it escalates **once** to a human notification (the agent is stranded), then stays quiet so a hard failure can't spam you. The respawn is cold (a fresh container), but it picks the task back up, so a one-off crash is invisible in practice.
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
A[Container stopped] --> B{How did it exit?}
|
||||
B -->|i_am_idle, clean| C[Reset error count]
|
||||
B -->|529 / 500 / 503 overload| D[Park the provider]
|
||||
B -->|crash| E{error_count < 3?}
|
||||
E -->|yes| F[Respawn on same task]
|
||||
E -->|no, == 3| G[Escalate once to a human]
|
||||
```
|
||||
|
||||
## Rate limits & overloads: park, probe, resume
|
||||
|
||||
When a provider pushes back, retrying immediately just burns tokens against a wall. So instead of crash-looping, RoboCo **parks** that provider and queues its work:
|
||||
|
||||
- A **rate limit (HTTP 429)** parks the provider. The agent reports `i_am_blocked(reason="rate_limited")`, the spawn gate stops launching new work for that provider, and a background loop probes for recovery.
|
||||
- A **persistent overload (HTTP 529 / 500 / 503)** parks the same way. The model SDK already retries genuinely transient blips; a *persistent* overload is detected from the dead container's log markers and parked rather than crash-retried straight back into the overload. This is gated by `ROBOCO_OVERLOAD_BREAK_ENABLED`, which is **on by default**.
|
||||
|
||||
The crucial property: **work is queued, never dropped.** Parked tasks wait; the background probe-and-resume loop requires a real `2xx` from the provider before it lifts the park and revives the parked agents. When the provider recovers, the queued work flows again on its own — you don't restart anything.
|
||||
|
||||
!!! info "The amber banner"
|
||||
While a provider is parked you'll see an amber banner across the panel: a per-provider countdown, how many agents are affected, and "operations paused — resuming automatically." It clears itself when the provider recovers. An empty banner means nothing is parked. The banner is driven live over the `/ws/system` WebSocket and re-syncs over HTTP if the socket drops — so a quiet provider reads as *paused, resuming*, not as a hang.
|
||||
|
||||
!!! tip "Parked is not stuck"
|
||||
If a run goes quiet, check the banner before assuming something broke. A parked provider with a counting-down timer is RoboCo waiting out a rate limit on purpose. The work is held and will resume — there's nothing for you to do.
|
||||
|
||||
## Next
|
||||
|
||||
- These guardrails are part of the broader [agent gateway](../company/agent-gateway.md) — agents are structurally constrained, not trusted to behave.
|
||||
- [Choosing a provider](./provider-routing.md) and [running on Grok](./grok.md).
|
||||
Reference in New Issue
Block a user