Team Brain
The Team Brain is one shared service per team. Every contributor’s workspace pushes
tier-tagged content to it via the aios CLI; the brain turns that stream into a live
dashboard of what the team is doing and deciding, and answers natural-language questions
over the whole corpus with cited sources.
You run one instance per team. It’s a Next.js + Postgres app you can self-host anywhere.
What you see
Section titled “What you see”The brain opens on Pulse — the team’s home surface. It leads with the brain’s synthesized understanding (the story of the team right now), not raw analytics.
Pulse answers “what is my team’s brain telling me right now?” in about ten seconds:
- Narrative arcs (the hero) — the brain reads across everyone’s synced work and writes the current storylines: what’s moving, who’s driving it, what it connects to.
- Working on — per person, their most recent day of work, with the evidence (tasks, decisions, deliverables) nested underneath.
- Timeline — the same work broken down day by day (collapsed by default).
- Metrics — knowledge growth, brain usage, and the task funnel (open for admins).
- Evidence trail — the raw events and atomic facts the arcs are built from.
A slim ask bar sits at the top of Pulse and hands any question straight to Chat.
Chat is a grounded question-and-answer over the team’s shared memory — Slack, decisions, tasks, code, meeting transcripts, and the knowledge graph. Every answer cites its sources, so you can trace a claim back to the item it came from.
Ask things like “what decisions were made about auth last sprint?” or “who owns onboarding, and what’s blocked?” — the answer streams in with the decisions, tasks, and documents it drew on linked inline.
Meetings
Section titled “Meetings”Meetings collects synced call transcripts and pulls out the action items and decisions from each one, so the follow-ups from a call become tracked work in the brain rather than dying in someone’s notes.
Codebases
Section titled “Codebases”Codebases shows the health, test coverage, and AI-transformation progress across the team’s repos, plus on-demand GitHub scans — the engineering surface of the same brain.
A repo only fills that dashboard once you wire it in. Linking a repo without the scan workflow leaves its readiness, health, and coverage permanently null.
Settings & Admin
Section titled “Settings & Admin”Everyone has an Account page to manage their own API keys. Admins additionally get an Admin area to invite members, issue and revoke keys, wire integrations, and pick the team’s active answering model (see Pluggable LLM).
How content gets in
Section titled “How content gets in”Contributors never write to the brain by hand. Each workspace runs aios push, which
sends its content to the narrow, audited ingest path:
Contributor workspaces (N×) │ │ aios push (POST /api/v1/items) ▼ ┌──────────────┐ │ Team Brain │ Next.js 16 + Postgres │ ingest lib │ narrow, audited write path │ query lib │ FTS + structured context + LLM streaming │ dashboard │ Pulse · Chat · Meetings · Codebases └──────────────┘Every item carries an access tier, and the brain enforces tier filtering on every read — in app code, since there is no row-level security backstop.
| Tier | Who can see it |
|---|---|
team | All authenticated team members |
external | All team members — it’s the outward-facing surface for clients/collaborators |
admin | Rejected at the ingest API with 422 — never stored |
Auth model:
- People sign in with email + password — invite-only (an admin creates the member row first, and that step is what mints the password). There is no OAuth sign-in: no Google, GitHub, or SSO provider button exists.
- Magic-link email is an optional second method, not the default. It appears on the
sign-in form only when the deployment has both
APP_URLand a mail provider (RESEND_API_KEYorSMTP_URL) set as environment variables. Without them the brain accepts the request, returns200, and silently delivers nothing — so treat the password as the real credential unless you have deliberately configured mail. - Machines authenticate with per-member API keys (
aios_<key_id>_<secret>, SHA-256 at rest, shown once at creation).
The brain is organized internally as eight organ systems — knowledge, ingestion, context, actions, identity, policy, audit, and feedback. See The 8 organ systems for the anatomy reference with shipped / partial / planned status.
Wire a repository into Codebases
Section titled “Wire a repository into Codebases”Content reaches the brain through aios push. Code does not. A repo reports itself
by running a scan-on-merge GitHub Actions workflow, which scans the checkout after every
merge and POSTs the result to /api/v1/codebases.
Without that workflow the brain still knows the repo exists — it falls back to the GitHub API for identity and contribution rows — but it has no checkout, so it deliberately writes no code metrics. A linked-but-unscanned repo shows null readiness, null health, and null coverage forever, and nothing anywhere reports an error.
Which repos need it
Section titled “Which repos need it”| Repo | What to do |
|---|---|
| A scaffolded workspace | Nothing — the scaffold ships .github/workflows/scan-on-merge.yml already. |
| Any other repo you want on the dashboard (product, service, docs) | Copy the workflow in by hand. |
The four files live in the toolkit scaffold at scaffold/.github/; copy all of them,
preserving paths:
.github/workflows/scan-on-merge.yml.github/scripts/fetch-brain-scanner.sh.github/scripts/scan_with_health.py.github/scripts/brain-scanner-requirements.txtThe workflow is repo-agnostic — it derives the codebase slug from GITHUB_REPOSITORY and
assumes nothing about the six-folder workspace spine, so it drops into an app or library
repo unchanged. It triggers on push to main; rename the branch in the on: block if
your default branch is something else.
The three repo secrets
Section titled “The three repo secrets”Every repo needs its own three GitHub Actions secrets. Actions secrets do not inherit across repositories — setting them once on one repo does nothing for the next. (An organization-level secret shared to the relevant repos is the sane answer once you have more than a handful.)
| Secret | Value |
|---|---|
AIOS_BRAIN_URL | Your brain’s base URL, e.g. https://your-brain.up.railway.app |
AIOS_TEAM | Your team slug |
AIOS_API_KEY | An API key belonging to a team-tier member (aios_<key_id>_<secret>) |
gh secret set AIOS_BRAIN_URL --body "https://your-brain.example.com" -R your-org/your-repogh secret set AIOS_TEAM --body "your-team" -R your-org/your-repogh secret set AIOS_API_KEY --body "aios_..." -R your-org/your-repoVerify a scan actually ran
Section titled “Verify a scan actually ran”This workflow is fail-open by design: if any of the three secrets is missing or blank
it prints a skip note and exits 0. That is intentional — a repo with no brain credentials
stays green rather than going red — but it means a green check is not evidence a scan
happened. This is the single most common way a repo silently stays off the dashboard.
A real scan takes roughly 60–90 seconds. A skipped one finishes in about 10.
gh run list -R your-org/your-repo --workflow scan-on-merge.yml --limit 1gh run view <run-id> -R your-org/your-repo --log \ | grep -E 'codebase_id|skipping the scan'| What you see | What it means |
|---|---|
{"status": "ok", "codebase_id": "..."} | The scan reached the brain. This is the proof. |
Brain credentials not configured — skipping the scan. | One or more secrets are unset or empty. Nothing was sent. |
403 forbidden_tier | The secrets resolved, but AIOS_API_KEY is not a team-tier key. |
Then confirm the row appears under Codebases in the dashboard with non-null readiness and health.
Run your own
Section titled “Run your own”The brain is self-host portable — plain SQL migrations, Postgres-backed rate limiting, no host-only dependencies. Any Postgres works; deploy anywhere that runs Next.js.
The fastest path is the Railway deploy template — the maintained one-click install, reached by direct link rather than by searching Railway’s public template gallery, which does not list it. It creates the Team Brain app and a managed Postgres service together, generates the application secrets, and asks only for your team and first-admin details. Railway shows the resources and estimated charges before you deploy. No GitHub fork or local Railway CLI is required. An active Railway plan in the workspace that will own the deployment is a prerequisite; an expired trial cannot create the project.
The first-admin password must be at least 10 characters. Railway’s form accepts a shorter one, and the deployment then fails while bootstrapping the admin, after Postgres has already been provisioned.
After the deployment is healthy, sign in with the admin credentials you supplied, create
an API key under Account, then return to aios onboard and connect the workspace with
the deployed Brain URL and that key.
For a local or non-Railway install, use the manual steps below.
-
Clone and install
Terminal window git clone https://github.com/aiosbrain/aios-team-braincd aios-team-brainnpm install -
Start a Postgres database
Any Postgres works. For a local throwaway DB, use the repo’s ephemeral test Postgres:
Terminal window npm run db:test:up # ephemeral Postgres on port 5434 -
Configure environment
Terminal window cp .env.example .env.localTerminal window DATABASE_URL=postgres://app:app@localhost:5434/app_testPGSSL=require # only for a managed Postgres with TLSAUTH_SECRET=<random string — signs the session cookie>SECRETS_KEY=<32 bytes, hex or base64 — encrypts stored connector secrets>APP_URL=http://localhost:3000ANTHROPIC_API_KEY=<your key># optional — magic-link login only. Password sign-in works without these.# RESEND_API_KEY=<your key># RESEND_FROM="Team Brain <brain@example.com>"# …or SMTP# SMTP_URL=smtp://user:pass@host:587# SMTP_FROM="Team Brain <brain@example.com>"The
DATABASE_URLabove matches the credentials the step-2 test database is created with (app/app/app_teston port 5434). Pointing atpostgres:postgresthere fails to authenticate andnpm run pg:schemadies in the next step.Generate
SECRETS_KEYwithopenssl rand -hex 32. The app boots without it — you get a[boot]warning, not a crash — but every Admin → Integrations connector save then fails withSECRETS_KEY is required to store/read connector secrets, and any feature that reads a stored connector secret returns a500. Set it before you start wiring integrations, and never rotate it without re-entering every secret: it is the AES-256-GCM key those ciphertexts were written with. -
Load the schema
Terminal window npm run pg:schema # loads postgres/schema.sql into DATABASE_URL -
Create your team and your admin login
Do not skip this. The schema creates tables, not accounts — without this step you reach the sign-in page with no credential to sign in with.
The admin CLI reads
DATABASE_URLfrom the environment rather than.env.local, so export it first:Terminal window export DATABASE_URL=postgres://app:app@localhost:5434/app_testnpm run admin -- create-team acme --name "Acme Robotics"npm run admin -- create-member you@acme.com \--name "Your Name" --handle you --role admin --team acmecreate-membergenerates a password and prints it once:✓ password set (copy now, shown once): <password>Copy it — that is how you log in. Pass
--password <your-own>to choose your own instead; either way it must be at least 10 characters. -
Seed demo data (optional)
Terminal window npx tsx --conditions react-server scripts/seed-demo.tsThis populates a separate
demoteam so the dashboard has something to show. The seed prints a demo API key once — save it if you want it. It is not a sign-in credential: seeded members are created without passwords and cannot log in. Your real login is the one from step 5. -
Run the dev server
Terminal window npm run dev# → http://localhost:3000Sign in at
/loginwith the email and password from step 5, then create your own API key under Account and point a workspace athttp://localhost:3000.
Deploying to production
Section titled “Deploying to production”For Railway, use the maintained Team Brain template; it provisions
the app, Postgres, schema bootstrap, public URL, and required secrets as one reviewed
bundle. For another host, provision a managed Postgres, point DATABASE_URL at it (PGSSL=require), and run
npm run pg:schema to load the schema. Add the required env vars (AUTH_SECRET,
APP_URL, email, ANTHROPIC_API_KEY) to your host, then deploy the aios-team-brain
repo. Point each workspace’s aios.yaml at the production URL.
Pluggable LLM
Section titled “Pluggable LLM”Answering is provider-agnostic. Admins choose the team’s active answering model from the Admin area — Anthropic, OpenRouter, or any OpenAI-compatible backend — and it applies to the whole team’s chat and synthesis (arcs, meeting extraction, and so on) through one switch. No rebuild required.
To run fully on-machine (no API cost), point the default at a local endpoint:
LLM_BASE_URL=http://localhost:11434/v1 # Ollama endpointLLM_MODEL=llama3.1 # any local modelEmbeddings and the reranker are a separate model class with their own configuration. See docs/PROVIDERS.md.
Query from the terminal
Section titled “Query from the terminal”Chat is also available over the CLI — the same tier-filtered, cited pipeline the dashboard uses:
aios query "what decisions were made about auth in sprint 1?"# → SSE stream: delta chunks, source citations, done signalThe pipeline: FTS retrieval over tier-filtered content → structured context injection (decisions, tasks, knowledge-graph entities) → LLM streaming, with per-member and per-team daily cost guards.