# Cerebe Documentation (/docs) **Cerebe Factory** puts a critic beside your coding agent on the workstation and an independent panel on every pull request. One verdict, bound to the commit. The panel posts its verdict as the `cerebe/critic` check. To gate merge on it, see [Require the check](/docs/factory/platform/github-app#require-the-check). Install in 30 seconds [#install-in-30-seconds] ```bash curl -fsSL https://cerebe.ai/install.sh | sh ``` That is the Factory binary — not `npm i @cerebe/sdk`, `pip install cerebe`, or the deprecated `@momentiq/dark-factory-cli`. The one line writes `cerebe/config.json`, `cerebe.yaml`, `AGENTS.md`, and `CLAUDE.md`. Local review stays **off** (0 critics, quorum 0) until `cerebe model add cursor` (or `claude` / `codex` / `gemini` / `kimi`). An empty fleet does not block push. The **CLI is free to run on any repository**. Plans and pricing for the hosted **Platform** are on the [pricing page](https://cerebe.ai/pricing). Start with Factory [#start-with-factory] Install, get your first review, and require the check. The workstation CLI and the hosted panel on every pull request. `review`, `watch`, `status`, `findings` — the workstation critic. Run a review, follow the factory floor, read the verdict. The rest of the platform [#the-rest-of-the-platform] Cerebe's cognitive substrate — memory, knowledge, retrieval, meta-learning — and the SDKs. Proven patterns, wired to Factory and AI Infra, via the `df-cerebe-template` scaffold. # AI Infra (/docs/ai-infra/overview) **AI Infra** is Cerebe's cognitive substrate: the memory, knowledge, retrieval, and meta-learning services that give an AI application real state. It is the layer the Cerebe Services team builds on, and it is available to you directly through the published SDKs and API. This section is **reference**. The API is live, the SDKs (`cerebe` on PyPI, `@cerebe/sdk` on npm) are published, and every request authenticates through the `X-API-Key` header (a `ck_live_` production key in these examples; see [Authentication](/docs/ai-infra/getting-started/authentication) for the full key taxonomy). There is no self-serve funnel here — if you want AI Infra wired into a product, [talk to us](https://cerebe.ai/services). What it provides [#what-it-provides] * **Memory Fabric** — hybrid vector + graph memory that persists across sessions. * **Knowledge Graph** — temporal knowledge that evolves with full provenance. * **Retrieval (RAG)** — hybrid embedding + retrieval over your own corpus. * **Meta-Learning** — the PLRE framework that models how a user learns. * **LLM Router** — OpenAI-compatible chat enriched with cognitive context. * **Storage** — S3-compatible object storage, bridged into the Memory Fabric. Quick example [#quick-example] ```python from cerebe import AsyncCerebe client = AsyncCerebe(api_key="ck_live_...") # Store a memory, tied to a durable entity await client.memory.add( content="User prefers visual explanations", session_id="session_abc", entity_id="user_123", ) # Later, in a different session, retrieve it by the same entity results = await client.memory.search( query="What does the user prefer?", session_id="*", # "*" searches across every session entity_id="user_123", # scoped to this entity ) # → results.data["memories"][0]["content"] == "User prefers visual explanations" ``` Get started [#get-started] Store and search your first memory in three minutes. Get a `ck_live_` API key and start making requests. Install the async-first `cerebe` SDK and explore the API. Install `@cerebe/sdk` for Node.js and the browser. # Blueprint (/docs/blueprint/overview) **Blueprint** is Cerebe's collection of proven patterns for building AI-native products — the shapes the Services team reaches for, wired to work with [Factory](/docs/factory/quickstart) and [AI Infra](/docs/ai-infra/overview) out of the box. It ships as a scaffold: the public [`df-cerebe-template`](https://github.com/momentiq-ai/df-cerebe-template) repo, which stands up an agent-native app (Bun + Hono + LangGraph.js + Svelte) with the Factory gate already armed. The template's `bun run init` sets the project up and wires the hooks — see the [template README](https://github.com/momentiq-ai/df-cerebe-template) for the full steps. Where it fits [#where-it-fits] * **Factory** reviews what you build — [get the workstation critic](/docs/factory/quickstart). * **AI Infra** gives the app real state — [memory, knowledge, retrieval](/docs/ai-infra/overview). * **Blueprint** is the starting shape that already connects the two. # Install (/docs/factory/install) The Cerebe Factory CLI runs on your workstation and is **free to run on any repository.** It is a compiled binary — not an npm or pip package. The hosted **Platform** is the independent panel on every pull request; see [the GitHub App](/docs/factory/platform/github-app). You do not need the App to use the CLI. Plans and pricing are on the [pricing page](https://cerebe.ai/pricing). Install the CLI [#install-the-cli] ```bash # From the repo you want adopted. curl -fsSL https://cerebe.ai/install.sh | sh ``` That one line downloads checksum-verified `cerebe` + `cyclone` binaries and configures **this** checkout (`cerebe install`, or `cerebe init` if already adopted). It writes `cerebe/config.json`, `cerebe.yaml`, `AGENTS.md`, and `CLAUDE.md`, arms git hooks, and runs `cerebe doctor`. It does **not** auto-enable a local critic fleet. Detected vendor CLIs are printed as a suggestion only. Day one is **0 critics, quorum 0**. `cerebe review` and `cerebe gate-push` **skip** when the fleet is empty — pre-push does **not** block just because no verdict exists. `cerebe.yaml` was previously named `darkfactory.yaml`. The CLI still reads a leftover `darkfactory.yaml`. Reusable workflows stay binaries-only: they set `CEREBE_INSTALL_DIR` to an isolated temp dir. `CI` and `CEREBE_SKIP_REPO=1` also skip repo setup. This is the Factory CLI. Do **not** install it with: * `npm i @momentiq/dark-factory-cli` — deprecated frozen npm CLI * `npm i @cerebe/sdk` or `pip install cerebe` — **Cerebe Cognitive**, a different product ([AI Infra](/docs/ai-infra/getting-started/quickstart)) * `npm i @cerebe/cli` — redirect stub that prints `install.sh` and exits 1 Local review is opt-in: ```bash cerebe model add cursor # or claude, codex, gemini, kimi ``` Once a critic is enabled, the hooks do this: * **post-commit** runs the critic in the background and writes a per-commit verdict. * **pre-push** requires a completed review and blocks the push if that verdict has an open `blocker` or `high` finding. A blocked push needs a named, recorded reason. On a repository that already has `cerebe/` committed — a teammate's clone, or a new git worktree — the same curl runs `cerebe init` instead of `cerebe install`. `cerebe doctor` already ran as the last step of the one-liner. An empty local fleet is OK. All-green does **not** mean the next commit will run a critic — that starts only after `cerebe model add`. Windows [#windows] The install script runs on macOS and Linux and stops on Windows. On Windows, download the `cerebe` and `cyclone` `.zip` archives for your architecture from the [Releases page](https://github.com/cerebe-ai/cerebe/releases), extract them, and put both binaries on your `PATH`. Then run `cerebe install` from the repository you want adopted, or `cerebe init` if it already has `cerebe/` committed. Pin a version [#pin-a-version] The install script installs the latest stable release. To install a specific release, set `CEREBE_VERSION` to its version number: ```bash curl -fsSL https://cerebe.ai/install.sh | CEREBE_VERSION=8.27.0 sh ``` Install to a required check, end to end. The workstation critic: `review`, `watch`, `status`, `findings`. # Quickstart (/docs/factory/quickstart) Cerebe reviews what your coding agent writes — on the workstation as you commit, and on the hosted **Platform** as an independent panel on every pull request. This is the short path from install to a required check. The **CLI is free to run on any repository.** Plans and pricing for the hosted **Platform** are on the [pricing page](https://cerebe.ai/pricing). 1. Install the CLI [#1-install-the-cli] ```bash curl -fsSL https://cerebe.ai/install.sh | sh ``` This is the Factory binary, not `npm i @cerebe/sdk`, `pip install cerebe`, or `npm i @momentiq/dark-factory-cli`. `@cerebe/cli` on npm is a stub that prints `install.sh` and exits 1. The one line writes `cerebe/config.json`, `cerebe.yaml`, `AGENTS.md`, and `CLAUDE.md`, arms the git hooks, and runs `cerebe doctor`. It does **not** auto-enable critics. Day one is 0 critics, quorum 0; `review` / `gate-push` skip when the fleet is empty. An empty fleet is OK. Local review is opt-in: ```bash cerebe model add cursor # or claude, codex, gemini, kimi ``` 2. Get your first review [#2-get-your-first-review] After `cerebe model add`, make a change with your agent, commit it, and watch the critic run: ```bash git commit -m "feat: ..." # post-commit starts the review in the background cerebe watch # follow the factory floor for this branch cerebe show --commit HEAD # read the full per-commit verdict ``` The workstation critic reads your repo's rules and reviews the diff. Findings at `blocker` or `high` hold your next push; lower severities are recorded and do not block. With no critic enabled, the commit and push go through without a local verdict. 3. Push through the gate [#3-push-through-the-gate] ```bash git push # with a fleet: needs a completed review with no blocker/high findings ``` If the gate blocks you, fix the finding in a **new commit** — never amend. The verdict is bound to the original commit and its diff, so an amend detaches the evidence rather than clearing it. A blocked push can only proceed with a named, recorded reason. An empty fleet does **not** fail closed on a missing verdict. 4. Require the check on your pull requests [#4-require-the-check-on-your-pull-requests] The workstation critic is a convenience; the authority is the hosted **Platform**. [Install the Cerebe GitHub App](https://github.com/apps/cerebe-factory/installations/new) on the repository. It posts its verdict on every pull request as the `cerebe/critic` check. To require it, add `cerebe/critic` to the repository's required status checks. The steps, and when the verdict blocks a merge, are in [Require the check](/docs/factory/platform/github-app#require-the-check). What the one curl installs, what it writes, and what the hooks do. `review`, `watch`, `status`, `findings` — the workstation critic in full. The hosted panel on every pull request, and how to require `cerebe/critic`. # Agent Traces (/docs/ai-infra/agents/traces) Agent Trace Ingestion [#agent-trace-ingestion] Feed your agent's execution traces into Cerebe and get structured memories, plan coherence analysis, and tool reliability tracking back. Your agents learn from every run. What Happens When You Ingest a Trace [#what-happens-when-you-ingest-a-trace] 1. **Step memories** — Each execution step is stored as an `execution_history` memory with importance scoring (failures score higher) 2. **Plan coherence** — If a plan was provided, Cerebe computes an LCS-based coherence score between planned and actual steps 3. **Tool reliability** — Per-tool success rates, latencies, and failure reasons are tracked in the agent's cognitive profile 4. **PEOA observation** — The trace triggers a Plan-Execute-Observe-Adapt cycle that updates the agent's strategy preferences Ingest a Trace [#ingest-a-trace] ```python result = await client.traces.ingest( trace_id="trace_001", task_id="research_task", agent_id="agent_alpha", steps=[ { "step_id": "s1", "node_name": "plan", "outcome": "success", "duration_ms": 120, "timestamp": "2025-01-15T10:00:00Z", }, { "step_id": "s2", "node_name": "search", "tool_name": "web_search", "outcome": "success", "duration_ms": 850, "timestamp": "2025-01-15T10:00:01Z", }, { "step_id": "s3", "node_name": "synthesize", "outcome": "success", "duration_ms": 200, "timestamp": "2025-01-15T10:00:02Z", }, ], plan={ "goal": "Research competitive landscape", "expected_steps": ["plan", "search", "synthesize"], }, outcome={ "success": True, "steps_taken": 3, "total_duration_ms": 1170, "result_summary": "Competitive analysis complete", }, ) print(result.memories_created) # 4 print(result.plan_coherence) # 1.0 (perfect adherence) print(result.tool_reliability_updated) # True ``` ```typescript const result = await client.traces.ingest({ traceId: 'trace_001', taskId: 'research_task', agentId: 'agent_alpha', steps: [ { stepId: 's1', nodeName: 'plan', outcome: 'success', durationMs: 120, timestamp: '2025-01-15T10:00:00Z' }, { stepId: 's2', nodeName: 'search', toolName: 'web_search', outcome: 'success', durationMs: 850, timestamp: '2025-01-15T10:00:01Z' }, { stepId: 's3', nodeName: 'synthesize', outcome: 'success', durationMs: 200, timestamp: '2025-01-15T10:00:02Z' }, ], plan: { goal: 'Research competitive landscape', expectedSteps: ['plan', 'search', 'synthesize'] }, outcome: { success: true, stepsTaken: 3, totalDurationMs: 1170, resultSummary: 'Competitive analysis complete' }, }) console.log(result.memoriesCreated) // 4 console.log(result.planCoherence) // 1.0 console.log(result.toolReliabilityUpdated) // true ``` ```bash curl -X POST https://api.cerebe.ai/api/v1/traces/ingest \ -H "X-API-Key: ck_live_..." \ -H "Content-Type: application/json" \ -d '{ "trace_id": "trace_001", "task_id": "research_task", "agent_id": "agent_alpha", "steps": [ {"step_id": "s1", "node_name": "plan", "outcome": "success", "duration_ms": 120, "timestamp": "2025-01-15T10:00:00Z"} ], "outcome": {"success": true, "steps_taken": 3, "total_duration_ms": 1170} }' ``` Plan Coherence Scoring [#plan-coherence-scoring] When you provide a `plan` with `expected_steps`, Cerebe computes a coherence score: * **1.0** — Agent followed the plan exactly * **0.5** — Significant divergence from plan * **0.0** — Complete deviation The score uses Longest Common Subsequence (LCS) ratio, so reordered steps still get partial credit. Tool Reliability Tracking [#tool-reliability-tracking] Every tool invocation in a trace updates the agent's cognitive profile with: * **Success rate** — EWMA-smoothed success rate per tool * **Average latency** — Smoothed latency tracking * **Last failure reason** — Most recent error for debugging * **Call count** — Total invocations Importance Scoring [#importance-scoring] Steps are automatically scored for memory importance: | Outcome | Base Score | | ----------------- | ---------- | | `failure` | 0.8 | | `timeout` | 0.7 | | `success` | 0.5 | | + tool invocation | +0.1 | Failures are scored higher because they're more valuable for learning. API Reference [#api-reference] | Method | Endpoint | Description | | ------ | ----------------------- | ------------------------- | | `POST` | `/api/v1/traces/ingest` | Ingest an execution trace | Next Steps [#next-steps] * [Cognitive Profiles](/docs/ai-infra/cognitive-profiles/overview) — See how traces build agent profiles * [Meta-Learning](/docs/ai-infra/meta-learning/overview) — PLRE/PEOA frameworks * [Memory Fabric](/docs/ai-infra/memory/overview) — Where trace memories are stored # Connect AI Tools (/docs/ai-infra/getting-started/ai-tools) Connect AI Tools [#connect-ai-tools] Cerebe exposes an MCP (Model Context Protocol) server, making it instantly accessible to AI coding tools like Claude Code, Cursor, Windsurf, and any MCP-compatible client. Why MCP? [#why-mcp] MCP lets your AI coding assistant directly access Cerebe's memory, knowledge, and cognitive services. Instead of copy-pasting API responses, your AI tool can: * **Search user memories** to understand context before generating code * **Ingest knowledge** from your codebase into the graph * **Track cognitive profiles** to personalize agent behavior * **Query learning patterns** to adapt content delivery Connect Claude Code [#connect-claude-code] Add to your `~/.claude/settings.json`: ```json { "mcpServers": { "cerebe": { "command": "npx", "args": ["-y", "@cerebe/mcp-server"], "env": { "CEREBE_API_KEY": "ck_live_..." } } } } ``` Then use natural language in Claude Code: ``` > Search cerebe memories for user_123's learning preferences > Ingest this conversation transcript into cerebe memory > What's the current PLRE state for user_456? ``` Connect Cursor [#connect-cursor] Add to your `.cursor/mcp.json`: ```json { "mcpServers": { "cerebe": { "command": "npx", "args": ["-y", "@cerebe/mcp-server"], "env": { "CEREBE_API_KEY": "ck_live_..." } } } } ``` Available MCP Tools [#available-mcp-tools] | Tool | Description | | ------------------ | -------------------------------------------------------- | | `memory_store` | Store a memory with type, importance, and metadata | | `memory_search` | Semantic search across all memories for an entity | | `memory_harvest` | Extract memories from a conversation transcript | | `knowledge_query` | Query the knowledge graph for entities and relationships | | `knowledge_ingest` | Add content to the knowledge graph | | `profile_get` | Get a user's cognitive profile | | `plre_state` | Get current PLRE learning phase | | `plre_transition` | Trigger a phase transition | | `trace_ingest` | Ingest an agent execution trace | Direct API Usage [#direct-api-usage] If your tool doesn't support MCP, you can use the REST API directly: ```bash curl -X POST https://api.cerebe.ai/api/v1/memory/search \ -H "X-API-Key: ck_live_..." \ -H "Content-Type: application/json" \ -d '{"query": "user preferences", "session_id": "*", "entity_id": "user_123", "limit": 5}' ``` Next Steps [#next-steps] * [Quickstart](/docs/ai-infra/getting-started/quickstart) — Store and search your first memory * [Authentication](/docs/ai-infra/getting-started/authentication) — API key management * [Python SDK](/docs/ai-infra/sdks/python) — Full Python SDK reference # Authentication (/docs/ai-infra/getting-started/authentication) Authentication [#authentication] All Cerebe API requests require an API key sent via the `X-API-Key` header. API Key Format [#api-key-format] ``` ck_live_aBcDeFgHiJkLmNoPqRsTuVwXyZ1234567890abc │ │ └── 43 characters of randomness (258-bit entropy) │ └── environment: live, test, admin └── cerebe key prefix ``` * **`ck_live_`** — Production keys * **`ck_test_`** — Development/testing keys * **`ck_admin_`** — Organization management keys Making Requests [#making-requests] ```python from cerebe import AsyncCerebe # API key from environment variable (recommended) client = AsyncCerebe() # reads CEREBE_API_KEY # Or pass explicitly client = AsyncCerebe(api_key="ck_live_...") ``` ```bash curl https://api.cerebe.ai/api/v1/memory/search \ -H "X-API-Key: ck_live_..." \ -H "Content-Type: application/json" \ -d '{"query": "hello", "session_id": "test"}' ``` Organizations & Projects [#organizations--projects] Cerebe uses an **Org > Project > Key** hierarchy: ``` Organization (org_xxx) └── Project (proj_xxx) # development, staging, production └── API Key (ck_live_xxx) ``` * **Organizations** — Your team or company * **Projects** — Isolated environments (dev, staging, prod) * **API Keys** — Scoped to a project with specific permissions Scopes [#scopes] API keys have permission scopes that control access: | Scope | Description | | ----------------- | ---------------------------- | | `memory:read` | Read/search memories | | `memory:write` | Store/update/delete memories | | `knowledge:read` | Query knowledge graph | | `knowledge:write` | Ingest into knowledge graph | | `storage:read` | Download files | | `storage:write` | Upload files | | `admin:*` | Full admin access | Rate Limiting [#rate-limiting] Every response includes rate limit headers: ``` X-RateLimit-Limit: 1000 X-RateLimit-Remaining: 847 X-RateLimit-Reset: 1709827200 ``` When you hit the limit, you'll receive a `429` response with a `Retry-After` header. Environment Variables [#environment-variables] The SDKs automatically read these environment variables: | Variable | Description | | ----------------- | ----------------------------------------------- | | `CEREBE_API_KEY` | Your API key | | `CEREBE_PROJECT` | Project ID (optional) | | `CEREBE_BASE_URL` | API base URL (default: `https://api.cerebe.ai`) | # Quickstart (/docs/ai-infra/getting-started/quickstart) Quickstart [#quickstart] Get from zero to your first API call in under 3 minutes. 1. Get Your API Key [#1-get-your-api-key] Sign in at [cerebe.ai/sign-in](https://cerebe.ai/sign-in) and create an API key from the [Dashboard](https://cerebe.ai/dashboard/keys). 2. Install the SDK [#2-install-the-sdk] ```bash pip install cerebe ``` ```bash npm install @cerebe/sdk ``` No installation needed — use curl directly. 3. Store a Memory [#3-store-a-memory] ```python from cerebe import AsyncCerebe client = AsyncCerebe(api_key="YOUR_API_KEY") await client.memory.add( content="User prefers visual explanations over text", entity_id="user_123", session_id="onboarding_session", type="semantic", importance=0.8, ) ``` ```typescript import Cerebe from '@cerebe/sdk' const client = new Cerebe({ apiKey: 'YOUR_API_KEY' }) await client.memory.add({ content: 'User prefers visual explanations over text', entityId: 'user_123', sessionId: 'onboarding_session', type: 'semantic', importance: 0.8, }) ``` ```bash curl -X POST https://api.cerebe.ai/api/v1/memory/store \ -H "X-API-Key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "content": "User prefers visual explanations over text", "entity_id": "user_123", "session_id": "onboarding_session", "memory_type": "semantic", "importance": 0.8 }' ``` 4. Search Memories [#4-search-memories] ```python results = await client.memory.search( query="What kind of explanations does the user like?", session_id="*", # "*" searches across every session entity_id="user_123", # scoped to the entity we stored under ) print(results.data["memories"]) # → [{"content": "User prefers visual explanations", ...}] ``` ```typescript const results = await client.memory.search({ query: 'What kind of explanations does the user like?', sessionId: '*', // "*" searches across every session entityId: 'user_123', // scoped to the entity we stored under }) console.log((results.data as { memories: unknown[] }).memories) // → [{ content: "User prefers visual explanations", ... }] ``` ```bash curl -X POST https://api.cerebe.ai/api/v1/memory/search \ -H "X-API-Key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "query": "What kind of explanations does the user like?", "session_id": "*", "entity_id": "user_123", "limit": 5 }' ``` Next Steps [#next-steps] * [Authentication](/docs/ai-infra/getting-started/authentication) — Understand API keys, orgs, and projects * [Memory API](/docs/ai-infra/memory/overview) — Full memory operations guide * [Knowledge Graph](/docs/ai-infra/knowledge/overview) — Build and query knowledge graphs * [Python SDK](/docs/ai-infra/sdks/python) — Complete Python SDK reference # Ingest Knowledge (/docs/ai-infra/knowledge/ingest) Ingest Knowledge [#ingest-knowledge] Ingest text content into Cerebe's Knowledge Graph. The system automatically extracts entities and relationships using Graphiti, building a temporal knowledge graph that evolves over time. Endpoint [#endpoint] ``` POST /api/v1/knowledge/ingest ``` Request Body [#request-body] | Parameter | Type | Required | Description | | ----------- | -------- | -------- | ----------------------------------------------------------- | | `content` | `string` | Yes | Text content to ingest into the knowledge graph | | `entity_id` | `string` | No | Entity to associate the knowledge with | | `source` | `string` | No | Source identifier (e.g., `onboarding_notes`, `lesson_plan`) | | `metadata` | `object` | No | Additional metadata for the ingestion | Examples [#examples] ```python from cerebe import AsyncCerebe client = AsyncCerebe(api_key="ck_live_...") result = await client.knowledge.ingest( content="Alice is a senior engineer at Acme Corp. She mentors Bob, who joined the team in January.", entity_id="team_alpha", source="onboarding_notes", ) print(result) # → {"entities_created": 3, "relationships_created": 2, "status": "completed"} ``` ```typescript import Cerebe from '@cerebe/sdk' const client = new Cerebe({ apiKey: 'ck_live_...' }) const result = await client.knowledge.ingest({ content: 'Alice is a senior engineer at Acme Corp. She mentors Bob, who joined the team in January.', entityId: 'team_alpha', source: 'onboarding_notes', }) console.log(result) // → { entitiesCreated: 3, relationshipsCreated: 2, status: "completed" } ``` ```bash curl -X POST https://api.cerebe.ai/api/v1/knowledge/ingest \ -H "X-API-Key: ck_live_..." \ -H "Content-Type: application/json" \ -d '{ "content": "Alice is a senior engineer at Acme Corp. She mentors Bob, who joined the team in January.", "entity_id": "team_alpha", "source": "onboarding_notes" }' ``` Response [#response] ```json { "entities_created": 3, "relationships_created": 2, "status": "completed" } ``` Status Values [#status-values] | Status | Description | | ------------- | ---------------------------------------- | | `completed` | Ingestion succeeded | | `unavailable` | Knowledge graph service is not available | How It Works [#how-it-works] 1. **Content Analysis** — The text is parsed to identify entities (people, organizations, concepts) and their relationships. 2. **Entity Extraction** — Graphiti extracts structured entities with types and properties. 3. **Relationship Mapping** — Connections between entities are identified and stored with temporal metadata. 4. **Temporal Tracking** — All facts include timestamps, enabling point-in-time queries (e.g., "Who was Bob's mentor in March?"). Error Responses [#error-responses] | Status | Description | | ------ | ----------------------------------- | | `401` | Missing or invalid API key | | `503` | Knowledge graph service unavailable | Next Steps [#next-steps] * [Query Knowledge](/docs/ai-infra/knowledge/query) — Search entities and relationships * [Knowledge Overview](/docs/ai-infra/knowledge/overview) — Full guide to the Knowledge Graph # Knowledge Graph (/docs/ai-infra/knowledge/overview) Knowledge Graph [#knowledge-graph] Cerebe's Knowledge Graph stores entities, relationships, and facts that evolve over time with full provenance. It provides temporal awareness — you can query what was true at any point in time, track how relationships change, and build a living model of any domain. Core Operations [#core-operations] Ingest Knowledge [#ingest-knowledge] Add content to the graph. Cerebe automatically extracts entities and relationships: ```python await client.knowledge.ingest( content="Alice is a senior engineer at Acme Corp. She mentors Bob.", entity_id="team_alpha", source="onboarding_notes", ) ``` Query the Graph [#query-the-graph] Search for entities and relationships: ```python results = await client.knowledge.query( query="Who does Alice mentor?", depth=2, limit=10, ) ``` Visualize [#visualize] Get graph data ready for visualization: ```python viz = await client.knowledge.visualize( query="team relationships", depth=3, ) # Returns nodes and edges for rendering ``` API Reference [#api-reference] | Method | Endpoint | Description | | ------ | ----------------------------- | ---------------------------- | | `POST` | `/api/v1/knowledge/ingest` | Add to knowledge graph | | `POST` | `/api/v1/knowledge/query` | Query entities/relationships | | `GET` | `/api/v1/knowledge/entities` | List entities | | `POST` | `/api/v1/knowledge/visualize` | Get visualization data | # Query Knowledge (/docs/ai-infra/knowledge/query) Query Knowledge [#query-knowledge] Query Cerebe's Knowledge Graph to find entities, relationships, and facts. Supports natural language queries with configurable traversal depth and filtering. Endpoint [#endpoint] ``` POST /api/v1/knowledge/query ``` Request Body [#request-body] | Parameter | Type | Required | Description | | -------------------- | ---------- | -------- | ----------------------------------------- | | `query` | `string` | Yes | Natural language or structured query | | `entity_id` | `string` | No | Starting entity for graph traversal | | `entity_type` | `string` | No | Filter results by entity type | | `relationship_types` | `string[]` | No | Filter by specific relationship types | | `depth` | `integer` | No | Maximum traversal depth, 1-5 (default: 2) | | `limit` | `integer` | No | Maximum results, 1-100 (default: 20) | Examples [#examples] ```python from cerebe import AsyncCerebe client = AsyncCerebe(api_key="ck_live_...") results = await client.knowledge.query( query="Who does Alice mentor?", depth=2, limit=10, ) for entity in results.entities: print(f"{entity.name} ({entity.entity_type})") for rel in results.relationships: print(f"{rel.source_id} --[{rel.relationship_type}]--> {rel.target_id}") ``` ```typescript import Cerebe from '@cerebe/sdk' const client = new Cerebe({ apiKey: 'ck_live_...' }) const results = await client.knowledge.query({ query: 'Who does Alice mentor?', depth: 2, limit: 10, }) for (const entity of results.entities) { console.log(`${entity.name} (${entity.entityType})`) } for (const rel of results.relationships) { console.log(`${rel.sourceId} --[${rel.relationshipType}]--> ${rel.targetId}`) } ``` ```bash curl -X POST https://api.cerebe.ai/api/v1/knowledge/query \ -H "X-API-Key: ck_live_..." \ -H "Content-Type: application/json" \ -d '{ "query": "Who does Alice mentor?", "depth": 2, "limit": 10 }' ``` Response [#response] ```json { "entities": [ { "id": "ent_abc123", "name": "Alice mentors Bob", "entity_type": "fact", "properties": null, "created_at": "2025-03-07T14:30:00Z" } ], "relationships": [], "total": 1 } ``` Entity Object [#entity-object] | Field | Type | Description | | ------------- | -------- | ------------------------------------------------------------ | | `id` | `string` | Unique entity identifier | | `name` | `string` | Entity name or fact description | | `entity_type` | `string` | Type classification (e.g., `person`, `organization`, `fact`) | | `properties` | `object` | Additional entity properties | | `created_at` | `string` | ISO-8601 creation timestamp | Relationship Object [#relationship-object] | Field | Type | Description | | ------------------- | -------- | --------------------------------------------------- | | `source_id` | `string` | Source entity ID | | `target_id` | `string` | Target entity ID | | `relationship_type` | `string` | Type of relationship | | `properties` | `object` | Relationship properties | | `valid_from` | `string` | When this relationship became true | | `valid_to` | `string` | When this relationship ended (null if still active) | Temporal Queries [#temporal-queries] The knowledge graph is temporal --- relationships have `valid_from` and `valid_to` fields. This enables point-in-time queries: ```python # Who was on the team in January? results = await client.knowledge.query( query="team members", entity_id="team_alpha", depth=1, ) ``` Error Responses [#error-responses] | Status | Description | | ------ | ----------------------------------- | | `401` | Missing or invalid API key | | `503` | Knowledge graph service unavailable | Next Steps [#next-steps] * [Ingest Knowledge](/docs/ai-infra/knowledge/ingest) — Add content to the graph * [Knowledge Overview](/docs/ai-infra/knowledge/overview) — Full guide to the Knowledge Graph # Chat Completions (/docs/ai-infra/llm/chat) Chat Completions [#chat-completions] Cerebe provides two chat completion endpoints: a **native API** with capability-based model routing, and an **OpenAI-compatible endpoint** that works as a drop-in replacement for `ChatOpenAI` or any OpenAI SDK client. Native Chat API [#native-chat-api] ``` POST /api/v1/llm/chat ``` The native endpoint supports model selection and domain context enrichment. Request Body [#request-body] | Parameter | Type | Required | Description | | ---------------- | ----------- | -------- | ----------------------------------- | | `messages` | `Message[]` | Yes | List of chat messages | | `model` | `string` | No | Model to use (default: `gpt-4o`) | | `temperature` | `float` | No | Sampling temperature (default: 0.7) | | `max_tokens` | `integer` | No | Maximum tokens in response | | `domain_context` | `object` | No | Domain context for enrichment | Message Object [#message-object] | Field | Type | Description | | --------- | ------------------ | ------------------------------------- | | `role` | `string` | `system`, `user`, or `assistant` | | `content` | `string \| object` | Message content (supports multimodal) | Examples [#examples] ```python from cerebe import AsyncCerebe client = AsyncCerebe(api_key="ck_live_...") response = await client.llm.chat( messages=[ {"role": "system", "content": "You are a helpful tutor."}, {"role": "user", "content": "Explain photosynthesis simply."}, ], ) print(response.choices[0]["message"]["content"]) ``` ```typescript import Cerebe from '@cerebe/sdk' const client = new Cerebe({ apiKey: 'ck_live_...' }) const response = await client.llm.chat({ messages: [ { role: 'system', content: 'You are a helpful tutor.' }, { role: 'user', content: 'Explain photosynthesis simply.' }, ], }) console.log(response.choices[0].message.content) ``` ```bash curl -X POST https://api.cerebe.ai/api/v1/llm/chat \ -H "X-API-Key: ck_live_..." \ -H "Content-Type: application/json" \ -d '{ "messages": [ {"role": "system", "content": "You are a helpful tutor."}, {"role": "user", "content": "Explain photosynthesis simply."} ] }' ``` Response [#response] ```json { "choices": [ { "message": { "role": "assistant", "content": "Photosynthesis is how plants make food from sunlight..." } } ], "usage": { "prompt_tokens": 25, "completion_tokens": 150, "total_tokens": 175 } } ``` OpenAI-Compatible Endpoint [#openai-compatible-endpoint] ``` POST /api/v1/openai/v1/chat/completions ``` This endpoint accepts the standard OpenAI request format, making Cerebe a drop-in replacement. It supports `tools`, `tool_choice`, and `stream` --- everything `ChatOpenAI` expects. Using with OpenAI SDK [#using-with-openai-sdk] ```python from openai import AsyncOpenAI # Point OpenAI client at Cerebe client = AsyncOpenAI( api_key="ck_live_...", base_url="https://api.cerebe.ai/api/v1/openai/v1", ) response = await client.chat.completions.create( model="gpt-4o", messages=[ {"role": "system", "content": "You are a helpful tutor."}, {"role": "user", "content": "What is 2+2?"}, ], ) print(response.choices[0].message.content) ``` ```typescript import OpenAI from 'openai' // Point OpenAI client at Cerebe const client = new OpenAI({ apiKey: 'ck_live_...', baseURL: 'https://api.cerebe.ai/api/v1/openai/v1', }) const response = await client.chat.completions.create({ model: 'gpt-4o', messages: [ { role: 'system', content: 'You are a helpful tutor.' }, { role: 'user', content: 'What is 2+2?' }, ], }) console.log(response.choices[0].message.content) ``` Using with LangChain [#using-with-langchain] ```python from langchain_openai import ChatOpenAI llm = ChatOpenAI( model="gpt-4o", openai_api_key="ck_live_...", openai_api_base="https://api.cerebe.ai/api/v1/openai/v1", ) response = await llm.ainvoke("Explain gravity") ``` Streaming [#streaming] Both endpoints support streaming. For the OpenAI-compatible endpoint, set `stream: true`: ```python from openai import AsyncOpenAI client = AsyncOpenAI( api_key="ck_live_...", base_url="https://api.cerebe.ai/api/v1/openai/v1", ) stream = await client.chat.completions.create( model="gpt-4o", messages=[{"role": "user", "content": "Tell me a story"}], stream=True, ) async for chunk in stream: if chunk.choices[0].delta.content: print(chunk.choices[0].delta.content, end="") ``` Capability-Based Routing [#capability-based-routing] When using the OpenAI-compatible endpoint, set the **canonical `X-LLM-Capability`** header to control model selection. The legacy `X-Cerebe-Capability` header is also accepted as an alias for backwards compatibility; when both are present, `X-LLM-Capability` wins. | Capability | Default Model | Use Case | | ---------------- | ------------- | ---------------------------- | | `standard` | GPT-5 | General chat and completions | | `vision` | GPT-5 | Multimodal/image requests | | `reasoning` | GPT-5 | Complex reasoning tasks | | `classification` | GPT-5 Mini | Lightweight classification | ```bash curl -X POST https://api.cerebe.ai/api/v1/openai/v1/chat/completions \ -H "X-API-Key: ck_live_..." \ -H "X-LLM-Capability: reasoning" \ -H "Content-Type: application/json" \ -d '{"messages": [{"role": "user", "content": "Solve this logic puzzle..."}]}' ``` Tool Calling [#tool-calling] The OpenAI-compatible endpoint fully supports function/tool calling: ```python response = await client.chat.completions.create( model="gpt-4o", messages=[{"role": "user", "content": "What's the weather in London?"}], tools=[{ "type": "function", "function": { "name": "get_weather", "description": "Get weather for a location", "parameters": { "type": "object", "properties": { "location": {"type": "string"} }, "required": ["location"] } } }], ) ``` Error Responses [#error-responses] | Status | Description | | ------ | --------------------------------------- | | `400` | Invalid request or preprocessing failed | | `401` | Missing or invalid API key | | `500` | LLM provider error | # Store Memory (/docs/ai-infra/memory/add) Store Memory [#store-memory] Store a memory into Cerebe's Memory Fabric. Memories are persisted across sessions and become searchable via semantic similarity, graph traversal, and keyword matching. Endpoint [#endpoint] ``` POST /api/v1/memory/store ``` Request Body [#request-body] | Parameter | Type | Required | Description | | ------------------- | ------------------ | -------- | ---------------------------------------------------------------------------------------------------------------- | | `content` | `string \| object` | Yes | The memory content to store | | `session_id` | `string` | Yes | Session identifier | | `entity_id` | `string` | No | Owner entity ID — the durable key that makes a memory retrievable across sessions (search with `session_id="*"`) | | `linked_entity_ids` | `string[]` | No | Related entity IDs to associate with the memory | | `memory_type` | `string` | No | One of `semantic`, `episodic`, `procedural`, `sequential`. Auto-detected if `domain_tag` is provided | | `domain_tag` | `string` | No | Domain classification: `conversation`, `insight`, `knowledge`, `preference` | | `importance` | `float` | No | Importance score from 0.0 to 1.0 (default: 0.5) | | `metadata` | `object` | No | Arbitrary key-value metadata attached to the memory | Examples [#examples] ```python from cerebe import AsyncCerebe client = AsyncCerebe(api_key="ck_live_...") result = await client.memory.add( content="User prefers visual explanations over text", entity_id="user_123", session_id="session_abc", type="semantic", importance=0.8, metadata={"source": "onboarding", "topic": "preferences"}, ) print(result.data) # → {"id": "mem_a1b2c3d4", "session_id": "session_abc", "memory_type": "semantic", ...} ``` ```typescript import Cerebe from '@cerebe/sdk' const client = new Cerebe({ apiKey: 'ck_live_...' }) const result = await client.memory.add({ content: 'User prefers visual explanations over text', entityId: 'user_123', sessionId: 'session_abc', type: 'semantic', importance: 0.8, metadata: { source: 'onboarding', topic: 'preferences' }, }) console.log(result.data) // → { id: "mem_a1b2c3d4", session_id: "session_abc", memory_type: "semantic", ... } ``` ```bash curl -X POST https://api.cerebe.ai/api/v1/memory/store \ -H "X-API-Key: ck_live_..." \ -H "Content-Type: application/json" \ -d '{ "content": "User prefers visual explanations over text", "session_id": "session_abc", "entity_id": "user_123", "memory_type": "semantic", "importance": 0.8, "metadata": {"source": "onboarding", "topic": "preferences"} }' ``` Response [#response] Returns `201 Created` on success: ```json { "message": "Memory stored successfully", "data": { "id": "mem_a1b2c3d4", "session_id": "session_abc", "memory_type": "semantic", "importance": 0.8, "timestamp": "2025-03-07T14:30:00Z" } } ``` Memory Types [#memory-types] | Type | Use Case | | ------------ | ---------------------------------------------------------------- | | `semantic` | Facts, knowledge, preferences — things that are generally true | | `episodic` | Events and experiences — things that happened at a specific time | | `procedural` | Skills and processes — how to do things | | `sequential` | Ordered sequences — steps in a workflow | Error Responses [#error-responses] | Status | Description | | ------ | ------------------------------------------------------------- | | `400` | Invalid request (empty content, invalid importance range) | | `401` | Missing or invalid API key | | `503` | Memory fabric unavailable (vector store or graph store error) | Next Steps [#next-steps] * [Search Memories](/docs/ai-infra/memory/search) — Find stored memories with semantic search * [Harvest Memories](/docs/ai-infra/memory/harvest) — Automatically extract memories from conversations * [Memory Overview](/docs/ai-infra/memory/overview) — Full guide to the Memory Fabric # Harvest Memories (/docs/ai-infra/memory/harvest) Harvest Memories [#harvest-memories] The Memory Harvester uses LLM-powered extraction to automatically identify and store memories from conversation transcripts. It detects facts, preferences, experiences, and skills mentioned in a chat and persists them to the Memory Fabric. Endpoint [#endpoint] ``` POST /api/v1/memory/harvest ``` Request Body [#request-body] | Parameter | Type | Required | Description | | ------------ | -------- | -------- | ----------------------------------------------------------------------------------------------- | | `session_id` | `string` | Yes | Session identifier (shared with memory fabric) | | `transcript` | `array` | Yes | Conversation transcript — an array of `{ role, content }` message objects (at least one) | | `entity_id` | `string` | No | Owner entity for the harvested memories, so they're retrievable across sessions for that entity | Options Object [#options-object] | Field | Type | Default | Description | | ----------------- | --------- | ------- | -------------------------------------------- | | `enabled` | `boolean` | `true` | Toggle harvesting on/off | | `max_memories` | `integer` | `4` | Maximum memories to extract per run (1-12) | | `min_confidence` | `float` | `0.55` | Confidence floor for persisting a memory | | `force_reharvest` | `boolean` | `false` | Ignore cached hashes and force re-extraction | Examples [#examples] ```python from cerebe import AsyncCerebe client = AsyncCerebe(api_key="ck_live_...") result = await client.memory.harvest( session_id="session_abc", transcript=[ {"role": "user", "content": "I really struggle with fractions"}, {"role": "assistant", "content": "Let me try a visual approach..."}, {"role": "user", "content": "Oh that makes much more sense! I love diagrams"}, ], entity_id="student_456", ) # The payload is a plain dict on `.data`. for memory in result.data["harvested_memories"]: print(f"[{memory['memory_type']}] {memory['summary']}") print(f" Confidence: {memory['confidence']}") ``` ```typescript import Cerebe from '@cerebe/sdk' const client = new Cerebe({ apiKey: 'ck_live_...' }) const result = await client.memory.harvest({ sessionId: 'session_abc', transcript: [ { role: 'user', content: 'I really struggle with fractions' }, { role: 'assistant', content: 'Let me try a visual approach...' }, { role: 'user', content: 'Oh that makes much more sense! I love diagrams' }, ], entityId: 'student_456', }) // The payload is on `result.data` (typed `unknown`); narrow it before use. const { harvested_memories } = result.data as { harvested_memories: Array<{ memory_type: string; summary: string; confidence: number }> } for (const memory of harvested_memories) { console.log(`[${memory.memory_type}] ${memory.summary}`) console.log(` Confidence: ${memory.confidence}`) } ``` ```bash curl -X POST https://api.cerebe.ai/api/v1/memory/harvest \ -H "X-API-Key: ck_live_..." \ -H "Content-Type: application/json" \ -d '{ "session_id": "session_abc", "transcript": [ {"role": "user", "content": "I really struggle with fractions"}, {"role": "assistant", "content": "Let me try a visual approach..."}, {"role": "user", "content": "Oh that makes much more sense! I love diagrams"} ], "entity_id": "student_456" }' ``` Response [#response] ```json { "session_id": "session_abc", "transcript_hash": "a1b2c3d4e5f6...", "harvested_memories": [ { "summary": "Student struggles with fractions", "memory_type": "episodic", "importance": 0.7, "confidence": 0.85, "source_turn_indices": [0], "metadata": {} }, { "summary": "Student prefers visual/diagram-based explanations", "memory_type": "semantic", "importance": 0.9, "confidence": 0.92, "source_turn_indices": [1, 2], "metadata": {} } ], "stored_memory_ids": ["mem_x1y2z3", "mem_a4b5c6"], "duration_ms": 1250.5, "warnings": [], "trace_id": "trace_abc123" } ``` How It Works [#how-it-works] 1. **Deduplication** — The transcript is hashed. If this exact transcript was already harvested, cached results are returned (unless `force_reharvest` is set). 2. **LLM Extraction** — An LLM analyzes the transcript and identifies candidate memories with type classification and confidence scores. 3. **Heuristic Fallback** — If the LLM is unavailable, a heuristic extractor identifies high-signal patterns (preferences, struggles, achievements). 4. **Confidence Filtering** — Only memories above `min_confidence` are persisted. 5. **Storage** — Accepted memories are stored in the Memory Fabric and become searchable immediately. Error Responses [#error-responses] | Status | Description | | ------ | ---------------------------------- | | `400` | Invalid request (empty transcript) | | `401` | Missing or invalid API key | | `500` | Harvest processing failed | Next Steps [#next-steps] * [Store Memory](/docs/ai-infra/memory/add) — Manually store individual memories * [Search Memories](/docs/ai-infra/memory/search) — Find harvested memories * [Memory Overview](/docs/ai-infra/memory/overview) — Full guide to the Memory Fabric # Memory (/docs/ai-infra/memory/overview) Memory [#memory] Cerebe's Memory Fabric provides persistent, searchable memory for your AI applications. Memories survive across sessions, enabling genuine personalization and context awareness. Memory Types [#memory-types] | Type | Description | Example | | ------------ | ---------------------- | ------------------------------------------ | | `semantic` | Facts and knowledge | "User is a software engineer" | | `episodic` | Events and experiences | "User struggled with algebra last session" | | `procedural` | Skills and processes | "User learns best with code examples" | Core Operations [#core-operations] Store a Memory [#store-a-memory] ```python await client.memory.add( content="User prefers dark mode and concise responses", entity_id="user_123", session_id="session_abc", type="semantic", importance=0.8, metadata={"source": "preferences", "topic": "ui"}, ) ``` Search Memories [#search-memories] Semantic similarity search across all stored memories: ```python results = await client.memory.search( query="What UI preferences does the user have?", session_id="*", # "*" searches across every session entity_id="user_123", # scoped to this entity limit=5, ) ``` Harvest from Conversations [#harvest-from-conversations] Automatically extract memories from a chat transcript: ```python await client.memory.harvest( session_id="session_abc", transcript=[ {"role": "user", "content": "I really love how you explained that visually..."}, ], ) ``` Consolidate [#consolidate] Merge near-duplicate memories to keep the fabric clean: ```python await client.memory.consolidate( entity_id="user_123", similarity_threshold=0.92, dry_run=True, # preview before merging ) ``` How It Works [#how-it-works] Cerebe's Memory Fabric combines three retrieval strategies for maximum recall: 1. **Vector Search** — Semantic similarity finds conceptually related memories even when exact words differ 2. **Graph Search** — Relationship traversal discovers connected memories through entity links and knowledge graphs 3. **Keyword Search** — BM25-based matching ensures exact terms and names are never missed Results are automatically fused and re-ranked to return the most relevant memories first. API Reference [#api-reference] | Method | Endpoint | Description | | -------- | ---------------------------- | ----------------------- | | `POST` | `/api/v1/memory/store` | Store a memory | | `POST` | `/api/v1/memory/search` | Search memories | | `GET` | `/api/v1/memory/{id}` | Get specific memory | | `PATCH` | `/api/v1/memory/{id}` | Update memory | | `DELETE` | `/api/v1/memory/{id}` | Delete memory | | `POST` | `/api/v1/memory/harvest` | Extract from transcript | | `POST` | `/api/v1/memory/consolidate` | Merge duplicates | # Search Memories (/docs/ai-infra/memory/search) Search Memories [#search-memories] Search across stored memories using semantic similarity. Cerebe fuses results from vector search (Qdrant), graph traversal (Neo4j/Graphiti), and BM25 keyword matching to return the most relevant memories. Endpoint [#endpoint] ``` POST /api/v1/memory/search ``` Request Body [#request-body] | Parameter | Type | Required | Description | | ----------------------- | ---------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `query` | `string` | Yes | Natural language search query | | `session_id` | `string` | Yes | Session identifier. Pass `"*"` to search across **every** session (cross-session retrieval); any other value scopes the search to that one session | | `limit` | `integer` | No | Maximum results (1-100, default: 5) | | `memory_types` | `string[]` | No | Filter by types: `semantic`, `episodic`, `procedural`, `sequential`. (The Python/TypeScript SDKs accept the alias `types` and translate it to this wire field.) | | `min_importance` | `float` | No | Minimum importance threshold (0.0-1.0) | | `entity_id` | `string` | No | Primary entity ID. Combine with `session_id="*"` to scope a cross-session search to one entity | | `linked_entity_ids` | `string[]` | No | Secondary entity IDs to include in search | | `retrieval_mode` | `string` | No | `vector` (default) or `hybrid` (BM25 + vector + graph) | | `include_graph_context` | `boolean` | No | Include graph neighbour context in results (default: false) | | `include_embeddings` | `boolean` | No | Include embedding vectors in response (default: false) | | `temporal_scope` | `string` | No | ISO-8601 date for point-in-time retrieval | Examples [#examples] ```python from cerebe import AsyncCerebe client = AsyncCerebe(api_key="ck_live_...") results = await client.memory.search( query="What kind of explanations does the user prefer?", session_id="session_abc", limit=5, types=["semantic", "episodic"], ) # `search` returns an APIResponse; the payload is a plain dict on `.data`. for memory in results.data["memories"]: print(f"[{memory['memory_type']}] {memory['content']}") print(f" Score: {memory['similarity_score']}") ``` ```typescript import Cerebe from '@cerebe/sdk' const client = new Cerebe({ apiKey: 'ck_live_...' }) const results = await client.memory.search({ query: 'What kind of explanations does the user prefer?', sessionId: 'session_abc', limit: 5, types: ['semantic', 'episodic'], }) // The payload is on `results.data` (typed `unknown`); narrow it before use. const { memories } = results.data as { memories: Array<{ memory_type: string; content: string; similarity_score: number }> } for (const memory of memories) { console.log(`[${memory.memory_type}] ${memory.content}`) console.log(` Score: ${memory.similarity_score}`) } ``` ```bash curl -X POST https://api.cerebe.ai/api/v1/memory/search \ -H "X-API-Key: ck_live_..." \ -H "Content-Type: application/json" \ -d '{ "query": "What kind of explanations does the user prefer?", "session_id": "session_abc", "limit": 5, "memory_types": ["semantic", "episodic"] }' ``` Response [#response] ```json { "memories": [ { "id": "mem_a1b2c3d4", "session_id": "session_abc", "content": "User prefers visual explanations over text", "memory_type": "semantic", "timestamp": "2025-03-07T14:30:00Z", "importance": 0.8, "access_count": 3, "last_accessed": "2025-03-07T16:00:00Z", "similarity_score": 0.92, "relationships": [], "metadata": {"source": "onboarding"} } ], "total": 1, "session_id": "session_abc" } ``` Retrieval Modes [#retrieval-modes] | Mode | Description | | -------- | ------------------------------------------------------------------------------------ | | `vector` | Semantic similarity search only (fastest, default) | | `hybrid` | Combines BM25 keyword search, vector similarity, and graph traversal for best recall | Hybrid mode is recommended when precision matters more than latency. It fuses results from all three retrieval strategies and re-ranks them. Cross-Session Search [#cross-session-search] By default a search is scoped to its `session_id`. To search across **every** session for the same entity, pass `session_id="*"` — which disables the per-session filter — and scope the results with `entity_id`: ```python results = await client.memory.search( query="learning preferences", session_id="*", # "*" disables the per-session filter entity_id="user_123", # scope the cross-session search to this entity ) ``` Error Responses [#error-responses] | Status | Description | | ------ | -------------------------- | | `401` | Missing or invalid API key | | `503` | Vector store unavailable | Next Steps [#next-steps] * [Store Memory](/docs/ai-infra/memory/add) — Add new memories to the fabric * [Harvest Memories](/docs/ai-infra/memory/harvest) — Auto-extract memories from conversations * [Memory Overview](/docs/ai-infra/memory/overview) — Full guide to the Memory Fabric # Analyze Patterns (/docs/ai-infra/meta-learning/analyze) Analyze Patterns [#analyze-patterns] Analyze a user's learning patterns over a specified time window. The system examines stored memories and interaction data to detect recurring patterns, preferences, and learning behaviors. Endpoint [#endpoint] ``` POST /api/v1/meta-learning/analyze ``` Request Body [#request-body] | Parameter | Type | Required | Description | | --------- | ---------- | -------- | ----------------------------------------------------------------- | | `user_id` | `string` | Yes | User to analyze | | `window` | `string` | No | Analysis time window (default: `7d`). Supports `7d`, `30d`, `90d` | | `domains` | `string[]` | No | Filter analysis to specific domains | Examples [#examples] ```python from cerebe import AsyncCerebe client = AsyncCerebe(api_key="ck_live_...") analysis = await client.meta_learning.analyze( user_id="user_123", window="30d", domains=["math", "science"], ) print(f"Total interactions: {analysis.total_interactions}") print(f"Patterns found: {len(analysis.patterns)}") for pattern in analysis.patterns: print(f"\n{pattern.pattern_type}: {pattern.description}") print(f" Confidence: {pattern.confidence}") print(f" Evidence: {pattern.evidence_count} data points") ``` ```typescript import Cerebe from '@cerebe/sdk' const client = new Cerebe({ apiKey: 'ck_live_...' }) const analysis = await client.metaLearning.analyze({ userId: 'user_123', window: '30d', domains: ['math', 'science'], }) console.log(`Total interactions: ${analysis.totalInteractions}`) console.log(`Patterns found: ${analysis.patterns.length}`) for (const pattern of analysis.patterns) { console.log(`\n${pattern.patternType}: ${pattern.description}`) console.log(` Confidence: ${pattern.confidence}`) console.log(` Evidence: ${pattern.evidenceCount} data points`) } ``` ```bash curl -X POST https://api.cerebe.ai/api/v1/meta-learning/analyze \ -H "X-API-Key: ck_live_..." \ -H "Content-Type: application/json" \ -d '{ "user_id": "user_123", "window": "30d", "domains": ["math", "science"] }' ``` Response [#response] ```json { "user_id": "user_123", "patterns": [ { "pattern_type": "memory_distribution", "description": "User has 15 episodic memories", "confidence": 0.95, "evidence_count": 15, "metadata": {"memory_type": "episodic"} }, { "pattern_type": "memory_distribution", "description": "User has 8 semantic memories", "confidence": 0.9, "evidence_count": 8, "metadata": {"memory_type": "semantic"} } ], "total_interactions": 23, "window": "30d", "analyzed_at": "2025-03-07T14:30:00Z" } ``` Pattern Object [#pattern-object] | Field | Type | Description | | ---------------- | --------- | -------------------------------------------------------------------------------------- | | `pattern_type` | `string` | Category of pattern (e.g., `memory_distribution`, `time_preference`, `topic_sequence`) | | `description` | `string` | Human-readable explanation of the pattern | | `confidence` | `float` | Confidence score from 0.0 to 1.0 | | `evidence_count` | `integer` | Number of data points supporting this pattern | | `metadata` | `object` | Pattern-specific details | Using Analysis Results [#using-analysis-results] Pattern analysis results can be used to personalize learning experiences: ```python analysis = await client.meta_learning.analyze(user_id="user_123", window="30d") # Use patterns to customize next session for pattern in analysis.patterns: if pattern.pattern_type == "memory_distribution": # Adjust content type mix based on memory distribution pass elif pattern.pattern_type == "modality_preference": # Prefer visual content if user responds better to it pass ``` Error Responses [#error-responses] | Status | Description | | ------ | ---------------------------- | | `401` | Missing or invalid API key | | `503` | Analysis service unavailable | Next Steps [#next-steps] * [PLRE Scoring](/docs/ai-infra/meta-learning/plre) — Understand how PLRE phases use pattern data * [Meta-Learning Overview](/docs/ai-infra/meta-learning/overview) — Full guide to the meta-learning system # Meta-Learning (/docs/ai-infra/meta-learning/overview) Meta-Learning [#meta-learning] Cerebe's Meta-Learning system analyzes how users learn across sessions, identifies patterns, and uses the PLRE (Prepare, Learn, Reinforce, Evaluate) framework to optimize educational experiences in real time. Why Meta-Learning? [#why-meta-learning] Most AI tutors treat every session independently. Cerebe's meta-learning layer builds a persistent understanding of each learner: * **Pattern Detection** — Identifies learning preferences, strengths, and growth areas across sessions * **PLRE Framework** — Guides learners through cognitively optimal phases * **Adaptive Personalization** — Adjusts content delivery based on accumulated insights * **Cross-Domain Transfer** — Recognizes patterns that apply across subjects Core Concepts [#core-concepts] Learning Patterns [#learning-patterns] The system detects patterns from memory and interaction data: | Pattern Type | Example | | --------------------- | ---------------------------------------------------- | | `time_preference` | "User is most engaged during morning sessions" | | `topic_sequence` | "User learns math better after a warm-up exercise" | | `modality_preference` | "User retains more from visual explanations" | | `memory_distribution` | "User has 15 episodic memories, 8 semantic memories" | PLRE Framework [#plre-framework] PLRE defines four cognitive phases that optimize learning: | Phase | Purpose | Key Metrics | | ------------- | ------------------------------------------- | ------------------------------------- | | **Prepare** | Activate prior knowledge, set context | Engagement level, cognitive readiness | | **Learn** | Introduce new concepts, active instruction | Cognitive load, comprehension signals | | **Reinforce** | Practice, apply, and solidify understanding | Retention rate, error patterns | | **Evaluate** | Assess mastery, identify gaps | Confidence score, accuracy metrics | The system automatically transitions between phases based on real-time signals. See [PLRE Scoring](/docs/ai-infra/meta-learning/plre) for details. Learner Profiles [#learner-profiles] Each user builds a persistent profile over time: ```python profile = await client.meta_learning.profile("user_123") print(profile.learning_style) # "visual-sequential" print(profile.strengths) # ["pattern recognition", "spatial reasoning"] print(profile.growth_areas) # ["long-form writing", "abstract concepts"] print(profile.preferred_modalities) # ["visual", "kinesthetic"] ``` API Reference [#api-reference] | Method | Endpoint | Description | | ------ | ----------------------------------------- | ----------------------------------------------------------------- | | `POST` | `/api/v1/meta-learning/analyze` | [Analyze learning patterns](/docs/ai-infra/meta-learning/analyze) | | `GET` | `/api/v1/meta-learning/profile/{user_id}` | Get learner profile | | `POST` | `/api/v1/meta-learning/plre/transition` | Trigger PLRE phase transition | | `GET` | `/api/v1/meta-learning/plre/state` | Get current PLRE state | Quick Example [#quick-example] ```python from cerebe import AsyncCerebe client = AsyncCerebe(api_key="ck_live_...") # Analyze patterns over the last 30 days analysis = await client.meta_learning.analyze( user_id="user_123", window="30d", ) for pattern in analysis.patterns: print(f"{pattern.pattern_type}: {pattern.description}") print(f" Confidence: {pattern.confidence}") ``` ```typescript import Cerebe from '@cerebe/sdk' const client = new Cerebe({ apiKey: 'ck_live_...' }) const analysis = await client.metaLearning.analyze({ userId: 'user_123', window: '30d', }) for (const pattern of analysis.patterns) { console.log(`${pattern.patternType}: ${pattern.description}`) console.log(` Confidence: ${pattern.confidence}`) } ``` Next Steps [#next-steps] * [Analyze Patterns](/docs/ai-infra/meta-learning/analyze) — Detect learning patterns for a user * [PLRE Scoring](/docs/ai-infra/meta-learning/plre) — Understand the PLRE framework in depth * [Memory API](/docs/ai-infra/memory/overview) — The memory data that powers meta-learning # PLRE Scoring (/docs/ai-infra/meta-learning/plre) PLRE Scoring [#plre-scoring] PLRE (Prepare, Learn, Reinforce, Evaluate) is Cerebe's cognitive framework for structuring learning sessions. It tracks where a learner is in their cognitive journey and provides real-time signals to optimize instruction. The Four Phases [#the-four-phases] Prepare [#prepare] Activate prior knowledge and set the context for new learning. * **Goal**: Prime the learner's working memory with relevant background * **Signals**: Engagement level, cognitive readiness * **Example**: "Let's review what you remember about fractions before we start decimals" Learn [#learn] Introduce new concepts through active instruction. * **Goal**: Present new material at an appropriate pace and complexity * **Signals**: Cognitive load, comprehension indicators * **Example**: "A decimal is another way to represent a fraction..." Reinforce [#reinforce] Practice, apply, and solidify understanding. * **Goal**: Move knowledge from working memory to long-term memory * **Signals**: Retention rate, error patterns, response time * **Example**: "Try converting these three fractions to decimals" Evaluate [#evaluate] Assess mastery and identify remaining gaps. * **Goal**: Measure understanding and determine next steps * **Signals**: Confidence score, accuracy, self-assessment alignment * **Example**: "Can you explain when you would use decimals vs fractions?" PLRE State [#plre-state] Each user/session has a PLRE state that tracks their current phase and cognitive metrics: ```json { "user_id": "user_123", "session_id": "session_abc", "current_phase": "learn", "phase_start": "2025-03-07T14:30:00Z", "engagement_level": 0.75, "cognitive_load": 0.6, "confidence": 0.45, "transition_history": [ { "from": "prepare", "to": "learn", "reason": "readiness_threshold_met", "timestamp": "2025-03-07T14:30:00Z" } ] } ``` State Metrics [#state-metrics] | Metric | Range | Description | | ------------------ | --------- | ----------------------------------------------- | | `engagement_level` | 0.0 - 1.0 | How actively engaged the learner is | | `cognitive_load` | 0.0 - 1.0 | Current mental effort (high = risk of overload) | | `confidence` | 0.0 - 1.0 | Learner's demonstrated understanding level | API Endpoints [#api-endpoints] Get Current State [#get-current-state] ``` GET /api/v1/meta-learning/plre/state?user_id=user_123&session_id=session_abc ``` ```python from cerebe import AsyncCerebe client = AsyncCerebe(api_key="ck_live_...") state = await client.meta_learning.plre_state( user_id="user_123", session_id="session_abc", ) print(f"Phase: {state.current_phase}") print(f"Engagement: {state.engagement_level}") print(f"Cognitive load: {state.cognitive_load}") print(f"Confidence: {state.confidence}") ``` ```typescript import Cerebe from '@cerebe/sdk' const client = new Cerebe({ apiKey: 'ck_live_...' }) const state = await client.metaLearning.plreState({ userId: 'user_123', sessionId: 'session_abc', }) console.log(`Phase: ${state.currentPhase}`) console.log(`Engagement: ${state.engagementLevel}`) console.log(`Cognitive load: ${state.cognitiveLoad}`) console.log(`Confidence: ${state.confidence}`) ``` ```bash curl "https://api.cerebe.ai/api/v1/meta-learning/plre/state?user_id=user_123&session_id=session_abc" \ -H "X-API-Key: ck_live_..." ``` Trigger Phase Transition [#trigger-phase-transition] ``` POST /api/v1/meta-learning/plre/transition ``` | Parameter | Type | Required | Description | | -------------- | -------- | -------- | --------------------------------------- | | `user_id` | `string` | Yes | User ID | | `session_id` | `string` | Yes | Session ID | | `target_phase` | `string` | No | Target phase (auto-detected if omitted) | | `reason` | `string` | No | Reason for the transition | ```python new_state = await client.meta_learning.plre_transition( user_id="user_123", session_id="session_abc", target_phase="reinforce", reason="comprehension_confirmed", ) print(f"Now in phase: {new_state.current_phase}") ``` ```typescript const newState = await client.metaLearning.plreTransition({ userId: 'user_123', sessionId: 'session_abc', targetPhase: 'reinforce', reason: 'comprehension_confirmed', }) console.log(`Now in phase: ${newState.currentPhase}`) ``` ```bash curl -X POST https://api.cerebe.ai/api/v1/meta-learning/plre/transition \ -H "X-API-Key: ck_live_..." \ -H "Content-Type: application/json" \ -d '{ "user_id": "user_123", "session_id": "session_abc", "target_phase": "reinforce", "reason": "comprehension_confirmed" }' ``` Phase Transition Logic [#phase-transition-logic] Transitions between phases are driven by cognitive signals: ``` Prepare ──→ Learn (engagement + readiness above threshold) Learn ──→ Reinforce (comprehension confirmed, cognitive load stable) Learn ──→ Prepare (cognitive overload detected, needs re-priming) Reinforce ──→ Evaluate (retention rate stabilized) Reinforce ──→ Learn (error patterns indicate gaps) Evaluate ──→ Prepare (new topic, cycle restarts) Evaluate ──→ Reinforce (mastery not yet achieved) ``` When `target_phase` is omitted from a transition request, the system automatically determines the optimal next phase based on current metrics. Using PLRE in Your Application [#using-plre-in-your-application] PLRE data enables you to build adaptive learning experiences: 1. **Check the current phase** at the start of each interaction 2. **Adjust content** based on the phase (e.g., simpler prompts during Prepare, challenging questions during Evaluate) 3. **Monitor cognitive load** to avoid overwhelming the learner 4. **Let transitions happen naturally** or trigger them manually when your application has additional context Next Steps [#next-steps] * [Analyze Patterns](/docs/ai-infra/meta-learning/analyze) — Detect learning patterns that feed into PLRE * [Meta-Learning Overview](/docs/ai-infra/meta-learning/overview) — Full guide to the meta-learning system * [Memory API](/docs/ai-infra/memory/overview) — The memory data that powers cognitive analysis # Manage Documents (/docs/ai-infra/rag/documents) Manage Documents [#manage-documents] RAG document management — embed, list, and delete. All operations are scoped to the organization of the API key. Embed a document [#embed-a-document] Chunks, embeds, and stores a document. Embedding an existing `source` replaces the previous chunks for that source (idempotent upsert). Endpoint [#endpoint] ``` POST /api/v1/rag/documents ``` Request Body [#request-body] | Parameter | Type | Required | Description | | ---------- | -------- | -------- | -------------------------------------------------------------------------------------------------------------- | | `source` | `string` | Yes | Stable identifier for the document (e.g. a file path or URL). Used as the primary key for updates and deletes. | | `content` | `string` | Yes | Full document text | | `doc_type` | `string` | No | Content type hint (default: `markdown`). Common values: `markdown`, `html`, `yaml`, `json`, `text` | | `metadata` | `object` | No | Arbitrary key-value metadata persisted with every chunk | Examples [#examples] ```python from cerebe import AsyncCerebe client = AsyncCerebe(api_key="ck_live_...") with open("docs/auth.md") as f: await client.rag.embed( source="docs/auth.md", content=f.read(), doc_type="markdown", metadata={"version": "v2", "team": "platform"}, ) ``` ```typescript import Cerebe from '@cerebe/sdk' import { readFileSync } from 'node:fs' const client = new Cerebe({ apiKey: 'ck_live_...' }) await client.rag.embed({ source: 'docs/auth.md', content: readFileSync('docs/auth.md', 'utf-8'), docType: 'markdown', metadata: { version: 'v2', team: 'platform' }, }) ``` ```bash curl -X POST https://api.cerebe.ai/api/v1/rag/documents \ -H "X-API-Key: ck_live_..." \ -H "Content-Type: application/json" \ -d '{ "source": "docs/auth.md", "content": "# Auth\n\nThe backend uses API keys...", "doc_type": "markdown", "metadata": {"version": "v2", "team": "platform"} }' ``` Response [#response] ```json { "message": "Document embedded", "data": { "status": "success", "source": "docs/auth.md", "chunks_created": 4, "doc_type": "markdown" } } ``` Chunking [#chunking] Documents are split with a recursive character splitter: * Chunk size: **1000 characters** (default) * Overlap: **200 characters** (default) * Separators preferred: paragraph breaks → line breaks → whitespace → character Smaller documents produce one chunk. Large documents produce many chunks that share surrounding context via the overlap. *** Batch embed [#batch-embed] Embed many documents in a single call. Faster than looping `embed()` because chunking, embedding, and persistence happen in batches. Endpoint [#endpoint-1] ``` POST /api/v1/rag/documents/batch ``` Request Body [#request-body-1] | Parameter | Type | Required | Description | | ----------- | ------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | | `documents` | `array` | Yes | Array of documents. Each item accepts the same fields as the single-embed request body: `source`, `content`, optional `doc_type`, optional `metadata`. | Examples [#examples-1] ```python result = await client.rag.embed_batch([ {"source": "docs/auth.md", "content": "..."}, {"source": "docs/storage.md", "content": "...", "doc_type": "markdown"}, {"source": "api/spec.yaml", "content": "...", "doc_type": "yaml"}, ]) print(result.data["total_chunks_created"]) ``` ```typescript const result = await client.rag.embedBatch({ documents: [ { source: 'docs/auth.md', content: '...' }, { source: 'docs/storage.md', content: '...', docType: 'markdown' }, { source: 'api/spec.yaml', content: '...', docType: 'yaml' }, ], }) console.log(result.data.total_chunks_created) ``` ```bash curl -X POST https://api.cerebe.ai/api/v1/rag/documents/batch \ -H "X-API-Key: ck_live_..." \ -H "Content-Type: application/json" \ -d '{ "documents": [ {"source": "docs/auth.md", "content": "..."}, {"source": "docs/storage.md", "content": "...", "doc_type": "markdown"} ] }' ``` Response [#response-1] ```json { "message": "Batch embedding completed", "data": { "status": "success", "documents_processed": 3, "total_chunks_created": 14, "results": [ { "source": "docs/auth.md", "chunks_created": 4, "status": "success" }, { "source": "docs/storage.md", "chunks_created": 7, "status": "success" }, { "source": "api/spec.yaml", "chunks_created": 3, "status": "success" } ] } } ``` *** List documents [#list-documents] Return every document in your organization's collection with its chunk count and last-updated timestamp. Endpoint [#endpoint-2] ``` GET /api/v1/rag/documents ``` Examples [#examples-2] ```python result = await client.rag.list_documents() for doc in result.data["documents"]: print(f"{doc['source']} ({doc['chunk_count']} chunks)") ``` ```typescript const result = await client.rag.listDocuments() for (const doc of result.data.documents) { console.log(`${doc.source} (${doc.chunk_count} chunks)`) } ``` ```bash curl https://api.cerebe.ai/api/v1/rag/documents \ -H "X-API-Key: ck_live_..." ``` Response [#response-2] ```json { "message": "Documents listed", "data": { "documents": [ { "source": "docs/auth.md", "doc_type": "markdown", "chunk_count": 4, "last_updated": "2026-04-19T20:56:14Z" } ], "total_documents": 1 } } ``` *** Delete a document [#delete-a-document] Remove every chunk for a given `source`. Safe to call on a non-existent source (returns `chunks_deleted: 0`). Endpoint [#endpoint-3] ``` DELETE /api/v1/rag/documents/{source} ``` The `source` path segment can contain slashes — FastAPI's `path` converter captures the full remainder after `/documents/`. Examples [#examples-3] ```python await client.rag.delete_document("docs/auth.md") ``` ```typescript await client.rag.deleteDocument({ source: 'docs/auth.md' }) ``` ```bash curl -X DELETE https://api.cerebe.ai/api/v1/rag/documents/docs/auth.md \ -H "X-API-Key: ck_live_..." ``` Response [#response-3] ```json { "message": "Document deleted", "data": { "status": "success", "source": "docs/auth.md", "chunks_deleted": 4 } } ``` # RAG (/docs/ai-infra/rag/overview) RAG [#rag] Cerebe's RAG resource lets you embed documents into a tenant-scoped vector space and retrieve the most relevant chunks for any query. Use it to ground LLM responses in your own docs, knowledge base, or any corpus — without shipping entire files as context. When to use which resource [#when-to-use-which-resource] Cerebe has three complementary retrieval surfaces. Pick the one that matches the data you're storing: | Resource | What it stores | Retrieval strategy | Typical use | | ----------- | ------------------------------------------------------------ | ---------------------------------------- | ---------------------------------------------------- | | `memory` | Personal / session context (facts, experiences, preferences) | Hybrid vector + graph + keyword | Long-term per-user memory | | `knowledge` | Structured entities and relationships | Graph traversal + temporal queries | Evolving knowledge graphs | | `rag` | Unstructured documents (text, markdown, HTML) | Semantic similarity over embedded chunks | Document search, docs grounding, knowledge-base Q\&A | Core Operations [#core-operations] Embed a document [#embed-a-document] ```python await client.rag.embed( source="docs/auth.md", content=open("docs/auth.md").read(), doc_type="markdown", ) # → chunks the document, embeds each chunk, stores in the vector index ``` Search [#search] ```python results = await client.rag.search( query="how does authentication work?", k=3, ) for r in results.data["results"]: print(r["source"], r["score"]) ``` Clean up [#clean-up] ```python await client.rag.delete_document("docs/auth.md") ``` How It Works [#how-it-works] 1. **Chunking** — documents are split into overlapping segments (default 1000 characters with 200-character overlap) so retrieval returns focused, self-contained snippets rather than entire files. 2. **Embedding** — each chunk is converted to a 1536-dimensional vector using `text-embedding-3-small`. 3. **Storage** — chunk metadata and content live in Postgres; vectors live in Qdrant. Both are scoped per organization. 4. **Retrieval** — query text is embedded with the same model, then cosine similarity is computed against the org's chunks. Top-`k` chunks are returned with their source, content, and similarity score. Multi-tenancy [#multi-tenancy] Every document and query is automatically scoped to the organization of your API key. You cannot see documents belonging to another org, and documents you embed are never exposed outside your org. This is enforced at the data layer — no bypass is possible through a missing header or malformed request. API Reference [#api-reference] | Method | Endpoint | Description | | -------- | -------------------------------- | --------------------------------------- | | `POST` | `/api/v1/rag/search` | Semantic document search | | `POST` | `/api/v1/rag/search/hybrid` | Weighted semantic + keyword search | | `POST` | `/api/v1/rag/search/similar` | Find documents similar to given content | | `POST` | `/api/v1/rag/documents` | Embed a document | | `POST` | `/api/v1/rag/documents/batch` | Batch embed documents | | `GET` | `/api/v1/rag/documents` | List embedded documents | | `DELETE` | `/api/v1/rag/documents/{source}` | Delete a document | | `GET` | `/api/v1/rag/stats` | Collection statistics | # Search Documents (/docs/ai-infra/rag/search) Search Documents [#search-documents] RAG exposes three retrieval surfaces — all operate over the chunks you've embedded via [`embed`](/docs/ai-infra/rag/documents) and are scoped to your organization. Semantic search [#semantic-search] Vector similarity search on the query's embedding. Endpoint [#endpoint] ``` POST /api/v1/rag/search ``` Request Body [#request-body] | Parameter | Type | Required | Description | | ---------------- | --------- | -------- | -------------------------------------------- | | `query` | `string` | Yes | Natural language search query (min length 1) | | `k` | `integer` | No | Number of results (1–20, default: 5) | | `doc_type` | `string` | No | Filter by document type (e.g. `markdown`) | | `source_pattern` | `string` | No | Substring match on the `source` field | Examples [#examples] ```python from cerebe import AsyncCerebe client = AsyncCerebe(api_key="ck_live_...") results = await client.rag.search( query="how does authentication work?", k=3, doc_type="markdown", ) for r in results.data["results"]: print(f"{r['source']} (score={r['score']:.3f})") print(r["content"][:200]) ``` ```typescript import Cerebe from '@cerebe/sdk' const client = new Cerebe({ apiKey: 'ck_live_...' }) const results = await client.rag.search({ query: 'how does authentication work?', k: 3, docType: 'markdown', }) for (const r of results.data.results) { console.log(`${r.source} (score=${r.score.toFixed(3)})`) console.log(r.content.slice(0, 200)) } ``` ```bash curl -X POST https://api.cerebe.ai/api/v1/rag/search \ -H "X-API-Key: ck_live_..." \ -H "Content-Type: application/json" \ -d '{ "query": "how does authentication work?", "k": 3, "doc_type": "markdown" }' ``` Response [#response] ```json { "message": "Search completed", "data": { "results": [ { "source": "docs/auth.md", "content": "Authentication uses API-key headers...", "score": 0.84, "metadata": { "version": "v2", "team": "platform" }, "doc_type": "markdown" } ] } } ``` `metadata` contains whatever was supplied at embed time — it is not auto-populated with `doc_type` or any other system fields. `score` is the cosine similarity in `[0, 1]`. Higher is more similar. *** Hybrid search [#hybrid-search] Weighted blend of semantic similarity and keyword overlap. Useful when queries contain specific terms, acronyms, or proper nouns that pure vector search can miss. Endpoint [#endpoint-1] ``` POST /api/v1/rag/search/hybrid ``` Request Body [#request-body-1] | Parameter | Type | Required | Description | | ----------------- | --------- | -------- | ------------------------------------------------- | | `query` | `string` | Yes | Natural language search query | | `k` | `integer` | No | Number of results (1–20, default: 5) | | `semantic_weight` | `float` | No | Weight for semantic score (0.0–1.0, default: 0.7) | | `keyword_weight` | `float` | No | Weight for keyword score (0.0–1.0, default: 0.3) | | `doc_type` | `string` | No | Filter by document type | The weights don't have to sum to 1.0 — the final score is a weighted sum and results are ranked by it. The default 0.7 / 0.3 split favours semantic matches while still surfacing exact-term hits. Examples [#examples-1] ```python results = await client.rag.hybrid_search( query="JWT middleware rate-limiting", k=5, semantic_weight=0.6, keyword_weight=0.4, ) ``` ```typescript const results = await client.rag.hybridSearch({ query: 'JWT middleware rate-limiting', k: 5, semanticWeight: 0.6, keywordWeight: 0.4, }) ``` ```bash curl -X POST https://api.cerebe.ai/api/v1/rag/search/hybrid \ -H "X-API-Key: ck_live_..." \ -H "Content-Type: application/json" \ -d '{ "query": "JWT middleware rate-limiting", "k": 5, "semantic_weight": 0.6, "keyword_weight": 0.4 }' ``` Response [#response-1] Hybrid results include both component scores alongside the final score so you can see what's driving the ranking: ```json { "message": "Hybrid search completed", "data": { "results": [ { "source": "docs/auth.md", "content": "...", "score": 0.78, "semantic_score": 0.81, "keyword_score": 0.72, "metadata": {}, "doc_type": "markdown" } ] } } ``` *** Find similar documents [#find-similar-documents] Given a content block, return the chunks most similar to it. Useful for "find related docs" or recommendation-style flows. Operates on the content's embedding (not a query embedding) so you can pass a paragraph, a title, or even an entire short document. Endpoint [#endpoint-2] ``` POST /api/v1/rag/search/similar ``` Request Body [#request-body-2] | Parameter | Type | Required | Description | | ---------- | --------- | -------- | ------------------------------------------- | | `content` | `string` | Yes | Content block to find similar documents for | | `k` | `integer` | No | Number of results (1–20, default: 5) | | `doc_type` | `string` | No | Filter by document type | Examples [#examples-2] ```python results = await client.rag.find_similar( content="JWT tokens are validated via the JWKS endpoint", k=3, ) ``` ```typescript const results = await client.rag.findSimilar({ content: 'JWT tokens are validated via the JWKS endpoint', k: 3, }) ``` ```bash curl -X POST https://api.cerebe.ai/api/v1/rag/search/similar \ -H "X-API-Key: ck_live_..." \ -H "Content-Type: application/json" \ -d '{ "content": "JWT tokens are validated via the JWKS endpoint", "k": 3 }' ``` Response shape is identical to `POST /api/v1/rag/search`. # Collection Stats (/docs/ai-infra/rag/stats) Collection Stats [#collection-stats] Return summary statistics for your organization's RAG collection — how many chunks, how many unique sources, and which document types are represented. Useful for dashboards, health checks, and capacity planning. Endpoint [#endpoint] ``` GET /api/v1/rag/stats ``` Examples [#examples] ```python from cerebe import AsyncCerebe client = AsyncCerebe(api_key="ck_live_...") stats = await client.rag.stats() print(stats.data) # → { # "total_chunks": 127, # "unique_sources": 34, # "document_types": {"markdown": 120, "yaml": 7}, # "embedding_model": "text-embedding-3-small", # "chunk_size": 1000, # "chunk_overlap": 200, # } ``` ```typescript import Cerebe from '@cerebe/sdk' const client = new Cerebe({ apiKey: 'ck_live_...' }) const stats = await client.rag.stats() console.log(stats.data) ``` ```bash curl https://api.cerebe.ai/api/v1/rag/stats \ -H "X-API-Key: ck_live_..." ``` Response [#response] ```json { "message": "Stats retrieved", "data": { "total_chunks": 127, "unique_sources": 34, "document_types": { "markdown": 120, "yaml": 7 }, "embedding_model": "text-embedding-3-small", "chunk_size": 1000, "chunk_overlap": 200 } } ``` | Field | Description | | ----------------- | -------------------------------------------------- | | `total_chunks` | Total number of embedded chunks in your org | | `unique_sources` | Number of distinct `source` values (documents) | | `document_types` | Chunk count broken down by `doc_type` | | `embedding_model` | Model used to produce the vector embeddings | | `chunk_size` | Chunk size in characters used when embedding | | `chunk_overlap` | Overlap size in characters between adjacent chunks | # Python SDK (/docs/ai-infra/sdks/python) Python SDK [#python-sdk] The official Python SDK for Cerebe. Provides both sync (`Cerebe`) and async (`AsyncCerebe`) clients. Installation [#installation] ```bash pip install cerebe ``` Quick Start [#quick-start] ```python from cerebe import Cerebe client = Cerebe(api_key="ck_live_...") # Store a memory client.memory.add( "User prefers visual explanations", "session_abc", type="semantic", importance=0.8, ) # Search memories results = client.memory.search("What does the user prefer?", "session_abc") ``` Async Client [#async-client] ```python from cerebe import AsyncCerebe async with AsyncCerebe(api_key="ck_live_...") as client: results = await client.memory.search( "user preferences", "session_abc", ) # Client automatically closed on exit ``` Every method on `Cerebe` has an identical async counterpart on `AsyncCerebe`. Resources [#resources] ```python client.memory # Memory operations (add, search, harvest, consolidate) client.knowledge # Knowledge graph (ingest, query, entities, visualize) client.rag # Retrieval-Augmented Generation (embed, search, stats) client.storage # File storage (upload, presigned URLs, extract) client.meta_learning # PLRE state, learning pattern analysis client.agents # Agent trace ingestion, working memory client.sessions # Session management, cognitive state client.graph # Graph traversal, temporal views ``` RAG Quick Start [#rag-quick-start] ```python # Embed a document with open("docs/auth.md") as f: client.rag.embed(source="docs/auth.md", content=f.read()) # Semantic search — returns top-k chunks ranked by similarity results = client.rag.search("how does authentication work?", k=3) for r in results.data["results"]: print(r["source"], r["score"]) ``` See [RAG docs](/docs/ai-infra/rag/overview) for the full API reference. Error Handling [#error-handling] ```python from cerebe import Cerebe from cerebe._errors import AuthenticationError, RateLimitError, NotFoundError try: result = client.memory.search("query", "sess_1") except AuthenticationError: print("Invalid API key") except RateLimitError as e: print(f"Rate limited. Retry after {e.retry_after}s") except NotFoundError: print("Resource not found") ``` Agent Integration [#agent-integration] ```python # Ingest execution traces client.agents.ingest_trace( "Called search tool with query 'quadratic formula'", "sess_123", metadata={"tool": "search", "latency_ms": 120}, ) # Set working memory with TTL client.agents.set_working_memory( "Current task: algebra homework", "sess_123", ttl_seconds=3600, ) ``` Configuration [#configuration] | Parameter | Environment Variable | Default | | ------------- | -------------------- | ----------------------- | | `api_key` | `CEREBE_API_KEY` | — (required) | | `project` | `CEREBE_PROJECT` | `""` | | `base_url` | `CEREBE_BASE_URL` | `https://api.cerebe.ai` | | `timeout` | — | `30.0` | | `max_retries` | — | `3` | Auto-Retry [#auto-retry] The SDK automatically retries on: * **429** (Rate Limited) — respects `Retry-After` header * **5xx** (Server Error) — exponential backoff Client errors (400, 401, 404, 422) are **never** retried. Requirements [#requirements] * Python 3.10+ * Dependencies: `httpx`, `pydantic`, `typing-extensions` # TypeScript SDK (/docs/ai-infra/sdks/typescript) TypeScript SDK [#typescript-sdk] The official TypeScript SDK for Cerebe. Works in Node.js 18+, browsers, Deno, and Bun. Installation [#installation] ```bash npm install @cerebe/sdk ``` Quick Start [#quick-start] ```typescript import Cerebe from '@cerebe/sdk' const client = new Cerebe({ apiKey: 'ck_live_...', }) // Store a memory await client.memory.add({ content: 'User prefers visual explanations', sessionId: 'session_abc', type: 'semantic', importance: 0.8, }) // Search memories const results = await client.memory.search({ query: 'What does the user prefer?', sessionId: 'session_abc', }) ``` Resources [#resources] ```typescript client.memory // Memory operations (add, search, harvest, consolidate) client.knowledge // Knowledge graph (ingest, query, entities, visualize) client.rag // Retrieval-Augmented Generation (embed, search, stats) client.storage // File storage (upload, presigned URLs, extract) client.metaLearning // PLRE state, learning pattern analysis client.agents // Agent trace ingestion, working memory client.sessions // Session management, cognitive state client.graph // Graph traversal, temporal views ``` RAG Quick Start [#rag-quick-start] ```typescript import { readFile } from 'node:fs/promises' // Embed a document (Node.js) await client.rag.embed({ source: 'docs/auth.md', content: await readFile('docs/auth.md', 'utf-8'), }) // Semantic search — returns top-k chunks ranked by similarity const results = await client.rag.search({ query: 'how does authentication work?', k: 3, }) for (const r of results.data.results) { console.log(r.source, r.score) } ``` See [RAG docs](/docs/ai-infra/rag/overview) for the full API reference. Error Handling [#error-handling] ```typescript import Cerebe, { AuthenticationError, RateLimitError, NotFoundError } from '@cerebe/sdk' try { const result = await client.memory.search({ query: '...', sessionId: 'sess_1' }) } catch (error) { if (error instanceof AuthenticationError) { console.log('Invalid API key') } else if (error instanceof RateLimitError) { console.log(`Retry after ${error.retryAfter}s`) } else if (error instanceof NotFoundError) { console.log('Resource not found') } } ``` Agent Integration [#agent-integration] ```typescript // Ingest execution traces await client.agents.ingestTrace({ content: 'Called search tool with query "quadratic formula"', sessionId: 'sess_123', metadata: { tool: 'search', latency_ms: 120 }, }) // Set working memory with TTL await client.agents.setWorkingMemory({ content: 'Current task: algebra homework', sessionId: 'sess_123', ttlSeconds: 3600, }) ``` Configuration [#configuration] | Parameter | Environment Variable | Default | | ------------ | -------------------- | ----------------------- | | `apiKey` | `CEREBE_API_KEY` | — (required) | | `project` | `CEREBE_PROJECT` | `""` | | `baseUrl` | `CEREBE_BASE_URL` | `https://api.cerebe.ai` | | `timeout` | — | `30000` (ms) | | `maxRetries` | — | `3` | Requirements [#requirements] * Node.js 18+ / modern browser / Deno / Bun * TypeScript 5.0+ (optional, for type checking) # Storage (/docs/ai-infra/storage/overview) Storage [#storage] Cerebe's Storage service provides S3-compatible file storage with built-in processing pipelines and optional bridging to the Memory Fabric. Uploaded content is not virus-scanned: an upload's `scan_status` moves from `pending` to `clean` when the upload completes, without inspecting the file. Upload files via multipart form, base64, or presigned URLs for direct browser uploads. Core Operations [#core-operations] Upload File (Multipart) [#upload-file-multipart] ``` POST /api/v1/storage/upload ``` Upload a file with optional processing and memory integration. | Parameter | Type | Required | Description | | ------------------ | --------- | -------- | ------------------------------------------------------- | | `file` | `file` | Yes | The file to upload (multipart) | | `session_id` | `string` | Yes | Session identifier | | `user_id` | `string` | Yes | User identifier | | `purpose` | `string` | No | Upload purpose (default: `memory`) | | `processing` | `string` | No | Comma-separated processor names (e.g., `ocr,summarize`) | | `bridge_to_memory` | `boolean` | No | Store extracted content as a memory (default: false) | | `tenant_id` | `string` | No | Tenant identifier (default: `cerebe`) | ```python import httpx # Multipart upload via REST API (not available in SDK — use base64 upload below for SDK) async with httpx.AsyncClient() as http: with open("essay.pdf", "rb") as f: response = await http.post( "https://api.cerebe.ai/api/v1/storage/upload", headers={"X-API-Key": "ck_live_..."}, files={"file": ("essay.pdf", f, "application/pdf")}, data={ "session_id": "session_abc", "user_id": "user_123", "purpose": "assessment", "processing": "ocr,summarize", "bridge_to_memory": "true", }, ) result = response.json() print(f"Upload ID: {result['upload_id']}") print(f"CDN URL: {result['cdn_url']}") ``` ```typescript // Multipart upload via REST API (not available in SDK — use base64 upload below for SDK) const form = new FormData() form.append('file', fs.createReadStream('essay.pdf')) form.append('session_id', 'session_abc') form.append('user_id', 'user_123') form.append('purpose', 'assessment') form.append('processing', 'ocr,summarize') form.append('bridge_to_memory', 'true') const response = await fetch('https://api.cerebe.ai/api/v1/storage/upload', { method: 'POST', headers: { 'X-API-Key': 'ck_live_...' }, body: form, }) const result = await response.json() console.log(`Upload ID: ${result.upload_id}`) console.log(`CDN URL: ${result.cdn_url}`) ``` ```bash curl -X POST https://api.cerebe.ai/api/v1/storage/upload \ -H "X-API-Key: ck_live_..." \ -F "file=@essay.pdf" \ -F "session_id=session_abc" \ -F "user_id=user_123" \ -F "purpose=assessment" \ -F "processing=ocr,summarize" \ -F "bridge_to_memory=true" ``` Upload Response [#upload-response] ```json { "upload_id": "upl_a1b2c3d4", "cdn_url": "https://cdn.cerebe.ai/uploads/upl_a1b2c3d4/essay.pdf", "status": "clean", "extracted": {"text": "...extracted content..."}, "memory_id": "mem_x1y2z3", "processing_status": "completed" } ``` Upload Base64 Content [#upload-base64-content] ``` POST /api/v1/storage/upload-base64 ``` Upload base64-encoded content. Useful for programmatic uploads without multipart form handling. ```python import base64 with open("image.png", "rb") as f: content_b64 = base64.b64encode(f.read()).decode() result = await client.storage.upload( content=content_b64, filename="image.png", content_type="image/png", session_id="session_abc", user_id="user_123", ) ``` ```bash curl -X POST https://api.cerebe.ai/api/v1/storage/upload-base64 \ -H "X-API-Key: ck_live_..." \ -H "Content-Type: application/json" \ -d '{ "content": "iVBORw0KGgo...", "filename": "image.png", "content_type": "image/png", "session_id": "session_abc", "user_id": "user_123" }' ``` Retrieve File Content [#retrieve-file-content] ``` GET /api/v1/storage/{upload_id}/content ``` Download the raw file content by upload ID. Returns the file as a streaming response with the original content type. ```python import httpx url = await client.storage.get_url(upload_id="upl_a1b2c3d4") async with httpx.AsyncClient() as http: response = await http.get(url) response.raise_for_status() with open("downloaded.pdf", "wb") as f: f.write(response.content) ``` ```typescript const { url } = await client.storage.getUrl('upl_a1b2c3d4') const response = await fetch(url) fs.writeFileSync('downloaded.pdf', Buffer.from(await response.arrayBuffer())) ``` ```bash curl https://api.cerebe.ai/api/v1/storage/upl_a1b2c3d4/content \ -H "X-API-Key: ck_live_..." \ -o downloaded.pdf ``` Presigned Upload URL [#presigned-upload-url] ``` POST /api/v1/storage/presigned-upload ``` Generate a presigned URL for direct browser-to-storage uploads, bypassing the API server for large files. | Parameter | Type | Required | Description | | -------------- | --------- | -------- | -------------------------------------- | | `file_name` | `string` | Yes | Original filename | | `file_type` | `string` | Yes | MIME type (e.g., `application/pdf`) | | `file_size` | `integer` | Yes | File size in bytes | | `content_hash` | `string` | Yes | SHA-256 hash for deduplication | | `tenant_id` | `string` | Yes | Tenant identifier | | `user_id` | `string` | No | User identifier | | `purpose` | `string` | No | Upload purpose (default: `assessment`) | ```python presigned = await client.storage.presigned_upload( file_name="large-video.mp4", file_type="video/mp4", file_size=52428800, content_hash="sha256_abc123...", tenant_id="my_app", ) print(f"Upload to: {presigned['upload_url']}") print(f"Expires in: {presigned['expires_in']}s") # Upload directly to the presigned URL import httpx async with httpx.AsyncClient() as http: with open("large-video.mp4", "rb") as f: await http.put(presigned["upload_url"], content=f.read()) ``` ```bash # Step 1: Get presigned URL curl -X POST https://api.cerebe.ai/api/v1/storage/presigned-upload \ -H "X-API-Key: ck_live_..." \ -H "Content-Type: application/json" \ -d '{ "file_name": "large-video.mp4", "file_type": "video/mp4", "file_size": 52428800, "content_hash": "sha256_abc123...", "tenant_id": "my_app" }' # Step 2: Upload directly to the returned URL curl -X PUT "" \ -H "Content-Type: video/mp4" \ --data-binary @large-video.mp4 ``` Presigned Response [#presigned-response] ```json { "status": "new", "upload_id": "upl_x1y2z3", "upload_url": "https://storage.cerebe.ai/presigned/...", "expires_in": 3600, "cdn_url": "https://cdn.cerebe.ai/uploads/upl_x1y2z3/large-video.mp4" } ``` Additional Endpoints [#additional-endpoints] | Method | Endpoint | Description | | ------ | ------------------------------------------- | -------------------------------------------------------------- | | `POST` | `/api/v1/storage/check-hash` | Check if a file already exists by content hash (deduplication) | | `GET` | `/api/v1/storage/{upload_id}/metadata` | Get upload metadata without downloading content | | `GET` | `/api/v1/storage/{upload_id}/ephemeral-url` | Generate a time-limited presigned URL for browser access | | `POST` | `/api/v1/storage/extract` | Apply processing to already-uploaded content | | `POST` | `/api/v1/storage/analyze-content` | Detect file type using Magika | Memory Bridge [#memory-bridge] When `bridge_to_memory` is enabled, the storage service extracts text content from the uploaded file and stores it as a memory in the Memory Fabric. This makes uploaded documents searchable via the [Memory Search API](/docs/ai-infra/memory/search). Error Responses [#error-responses] | Status | Description | | ------ | --------------------------------------------------------------------------------------------------------- | | `400` | Invalid request (bad base64, missing fields) | | `401` | Missing or invalid API key | | `403` | Upload not available yet (`scan_status` is not `clean`, e.g. a presigned upload that was never completed) | | `404` | Upload not found | | `500` | Storage processing failed | Next Steps [#next-steps] * [Memory API](/docs/ai-infra/memory/overview) — Search through content bridged from uploads * [Authentication](/docs/ai-infra/getting-started/authentication) — API key management # CLI overview (/docs/factory/cli/overview) The Cerebe **CLI** is the workstation half of Cerebe. It reviews what your coding agent writes, on every commit, against your repo's rules — so slop is caught before the pull request exists. The **CLI is free to run on any repository.** The hosted **Platform** is the independent panel on every pull request, the dashboard, and the `cerebe/critic` check. Plans and pricing are on the [pricing page](https://cerebe.ai/pricing). This page covers the workstation critic. The loop [#the-loop] `cerebe install` arms two git hooks (see [Install](/docs/factory/install)) but does **not** enable critics. Local review starts after `cerebe model add cursor` (or `claude` / `codex` / `gemini` / `kimi`). Until then, `review` and `gate-push` skip. After you add a critic, the loop is: ```bash git commit -m "feat: ..." # post-commit runs the critic in the background cerebe watch # follow the review as it runs git push # pre-push needs a completed review, blocks on blocker / high ``` The commands [#the-commands] | Command | What it does | | ------------------------------------------- | --------------------------------------------------------------------------------------- | | `cerebe review` | Run the local critic against a commit (the post-commit hook usually does this for you). | | `cerebe watch` | Live "factory floor" for this branch's review loop. | | `cerebe status --commit HEAD` | Terse verdict + per-critic status for one commit. | | `cerebe show --commit HEAD` | Render the full per-commit review artifact. | | `cerebe findings --range origin/main..HEAD` | Audit findings across a range (does not re-gate). | | `cerebe stats` | Summarize the critic audit trail, including overrides. | | `cerebe doctor` | Report armed hooks, detected agents, and config health. | The critics [#the-critics] Local review is opt-in. `cerebe install` leaves `critics[]` empty. Add one with `cerebe model add `. After that, the local critic runs a **multi-vendor quorum** using your own AI-app subscriptions — the CLIs you already run, such as Claude Code, Codex, and Cursor. There are no API keys to manage; the fleet and the quorum come from `cerebe/config.json`. Run a review, read the verdict, and address findings the right way. The hosted panel on every pull request, posted as the `cerebe/critic` check. # Review & watch (/docs/factory/cli/review-and-watch) The workstation critic reviews each commit and gates your push on the result — **after** you opt in with `cerebe model add`. `cerebe install` leaves the local fleet empty; `review` / `gate-push` then skip and do not block. The CLI is **free to run on any repository**. Plans and pricing for the hosted Platform are on the [pricing page](https://cerebe.ai/pricing). Run a review [#run-a-review] A review normally starts on its own from the **post-commit** hook. To run it directly against the current commit: ```bash cerebe review ``` The critic reads your repo's rules, reviews the diff, and writes a per-commit verdict, running a multi-vendor quorum from your AI-app subscriptions. Follow the factory floor [#follow-the-factory-floor] ```bash cerebe watch ``` `watch` streams each critic's progress and the aggregate verdict as it settles for the current branch. Read the verdict [#read-the-verdict] ```bash cerebe status --commit HEAD # terse: verdict + per-critic status cerebe show --commit HEAD # full artifact: findings, severities, rationale ``` Findings are tiered: `blocker` and `high` hold your next push; everything below does not block and stays on the record as a dissent. Push through the gate [#push-through-the-gate] ```bash git push ``` With a local fleet enabled, the **pre-push** gate needs a completed review for the HEAD commit and blocks if that verdict has an open `blocker` or `high` finding. It also fails closed when the post-commit review hasn't produced a verdict yet (`blockOnMissingReview`), so an unreviewed push never slips through — wait for `cerebe watch` to settle, then push. That fail-close applies only after you have enabled at least one critic. An empty fleet (the `cerebe install` default) skips the gate; it does **not** block because no verdict exists. If you're blocked by a finding, **fix it in a new commit** — never amend. The verdict is bound to the original commit's SHA and diff hash, so an amend detaches the evidence instead of clearing it. A push blocked by something genuinely outside your change can be bypassed, but the bypass is loud: it takes a named, recorded reason and is written to the audit trail. Audit a range [#audit-a-range] ```bash cerebe findings --range origin/main..HEAD # every finding on the branch cerebe stats # the audit trail, including bypasses ``` `findings` reads the recorded findings across a range without re-running the gate. The full command surface of the workstation critic. The hosted panel on every pull request, and how to require `cerebe/critic`. # The GitHub App (/docs/factory/platform/github-app) The **Platform** is the hosted half of Cerebe: the GitHub App runs an independent panel on every pull request and posts one verdict as the `cerebe/critic` check. It is the authority the workstation CLI defers to. Plans and pricing are on the [pricing page](https://cerebe.ai/pricing). Install the App [#install-the-app] [Install the Cerebe GitHub App](https://github.com/apps/cerebe-factory/installations/new) on a repository or an organization. Once it's installed, every pull request runs the panel automatically — no workflow YAML to add, and no model keys to store in your CI. Sign in at [factory.cerebe.ai](https://factory.cerebe.ai) for the dashboard across your repositories. Require the check [#require-the-check] The App posts its verdict on every pull request as one check, named `cerebe/critic`. On a paid plan, when `cerebe/critic` is a required status check, a pull request merges only on an approving verdict, and a missing verdict blocks. Without a paid plan, or until the check is required, the verdict is posted and does not block. To require the check, add `cerebe/critic` to the repository's required status checks, with a ruleset or with a branch protection rule. With a ruleset: 1. On GitHub, open the repository's **Settings**, then **Rules**, then **Rulesets**. 2. Select **New ruleset**, then **New branch ruleset**, or open the ruleset that already covers the branch. 3. Name it, set **Enforcement status** to **Active**, and under **Target branches** add the branch you merge into. 4. Turn on **Require status checks to pass**, select **Add checks**, and search for `cerebe/critic`. 5. Select the `cerebe/critic` entry posted by the Cerebe GitHub App (GitHub lists the App as **Cerebe Factory**), then save the ruleset. With a branch protection rule: 1. On GitHub, open the repository's **Settings**, then **Branches**. 2. Select **Add classic branch protection rule**, or **Edit** on the rule for the branch you merge into. 3. Turn on **Require status checks to pass before merging** and search for `cerebe/critic`. 4. Select it, choose the Cerebe GitHub App (**Cerebe Factory**) as its source, and save the rule. If `cerebe/critic` is not in the search results, open or update a pull request so the App posts the check, then search again. What the panel does [#what-the-panel-does] Independent critics from rival model families review the change in parallel, each on its own, and a deterministic kernel turns their findings into one verdict — the same kernel that runs on your workstation. The workstation critic is a convenience that shares this kernel; the hosted App runs its own independent critic fleet and remains the authority that gates merge. On the Platform, blocking takes **corroboration**: a blocking finding holds the merge when a second independent critic reports it at the same place, and a finding that stands alone is kept on the record as a dissent. Every verdict is bound to the commit SHA and its diff — amend the commit and the panel re-runs, and a stale diff is rejected rather than judged. Overriding the check takes a named person and a recorded reason. Choose the repositories the panel reviews. The free workstation critic that runs before the pull request exists. Plans and pricing are on the pricing page. # Cognitive Profiles (/docs/ai-infra/cognitive-profiles/overview) Cognitive Profiles [#cognitive-profiles] Cognitive Profiles are Cerebe's persistent representation of how a user or agent operates. They evolve automatically over time through PLRE analysis and PEOA observation cycles, enabling deeply personalized interactions without manual configuration. What's in a Profile? [#whats-in-a-profile] Human Profiles [#human-profiles] Built from learning sessions and meta-learning analysis: | Field | Description | Example | | ---------------------- | --------------------------------- | ------------------------- | | `active_phase` | Current PLRE learning phase | `"learn"` | | `engagement_level` | Smoothed engagement metric (EWMA) | `0.82` | | `cognitive_load` | Current cognitive load estimate | `0.45` | | `confidence` | Learner confidence score | `0.71` | | `preferred_modalities` | Detected learning modalities | `["visual", "code"]` | | `reinforcement_topics` | Topics needing reinforcement | `["recursion", "graphs"]` | | `session_count` | Total sessions analyzed | `47` | Agent Profiles [#agent-profiles] Built from execution traces and PEOA observations: | Field | Description | Example | | ---------------------- | ------------------------------------- | ------------------------------------------- | | `task_success_rate` | Smoothed success rate | `0.89` | | `execution_efficiency` | Steps-taken vs steps-planned | `0.76` | | `plan_coherence_drift` | How much execution diverges from plan | `0.12` | | `tool_reliability` | Per-tool success rate and latency | `{"search": {success: 0.95, latency: 120}}` | | `preferred_strategies` | Detected strategy patterns | `["depth_first", "verify_then_act"]` | Get a Profile [#get-a-profile] ```python profile = await client.profiles.get("user_123") print(profile.engagement_level) # 0.82 print(profile.preferred_modalities) # ["visual", "code"] print(profile.active_phase) # "learn" ``` ```typescript const profile = await client.profiles.get('user_123') console.log(profile.engagementLevel) // 0.82 console.log(profile.preferredModalities) // ["visual", "code"] console.log(profile.activePhase) // "learn" ``` ```bash curl https://api.cerebe.ai/api/v1/meta-learning/profile/user_123 \ -H "X-API-Key: ck_live_..." ``` How Profiles Evolve [#how-profiles-evolve] Profiles update automatically — you don't need to manage them manually. **For humans:** Every PLRE analysis cycle updates engagement, confidence, cognitive load, and modality preferences using exponentially weighted moving averages (EWMA). This ensures recent sessions have more influence while maintaining stability. **For agents:** Every trace ingestion triggers a PEOA observation that updates task success rate, tool reliability scores, strategy preferences, and plan coherence metrics. Multi-Agent Coordination [#multi-agent-coordination] Cognitive profiles support hierarchical memory scoping: * **Private** — Only the creating agent can read/write * **Task-shared** — All agents on the same task can read (creator writes) * **Org-shared** — All agents in the organization can read This enables teams of agents to share cognitive context without conflicts, with optimistic concurrency control protecting against write races. API Reference [#api-reference] | Method | Endpoint | Description | | ------ | ----------------------------------------- | ------------------------ | | `GET` | `/api/v1/meta-learning/profile/{user_id}` | Get cognitive profile | | `POST` | `/api/v1/meta-learning/plre/transition` | Update PLRE phase | | `GET` | `/api/v1/meta-learning/plre/state` | Get current PLRE state | | `POST` | `/api/v1/meta-learning/analyze` | Trigger pattern analysis | Next Steps [#next-steps] * [Meta-Learning](/docs/ai-infra/meta-learning/overview) — PLRE framework and pattern detection * [Agent Traces](/docs/ai-infra/agents/traces) — Feed execution traces to build agent profiles * [Memory Fabric](/docs/ai-infra/memory/overview) — The memory layer that profiles draw from