# LocusGraph Builder Documentation
> Build intelligent agents with LocusGraph - A deterministic memory system for AI agents
## Coding Agent Integration
Terminal commands, file edits, error tracking, and user intent.
import { Callout } from '../../components/Callout.tsx'
import { LinkCard } from '../../components/link-card.tsx'
import { CodeGroup } from '../../components/code-group.tsx'
### What Coding Agents Know
Coding agents generate unique knowledge that compounds across sessions: commands run, files edited, errors hit, and user instructions. Storing this knowledge turns a stateless tool into a learning assistant.
### Event Types for Coding Agents
#### Terminal Commands
Store commands as action events. Include the result and duration for future reference.
```typescript
await client.storeEvent({
graph_id: 'project-x',
event_kind: 'action',
source: 'executor',
context_id: 'project:api_server',
payload: { command: 'cargo test', result: 'PASS', duration_ms: 3200 },
});
```
#### Errors
Store errors as observation events. Track which errors recur and what fixed them.
```typescript
await client.storeEvent({
graph_id: 'project-x',
event_kind: 'observation',
source: 'agent',
context_id: 'error:null_pointer',
payload: { file: 'src/auth.rs', line: 42, message: 'unwrap on None value', fix: 'Use Option::unwrap_or_default()' },
});
```
#### User Intent
Store what the user asked for and why as decision events. This helps the agent align future actions with user preferences.
```typescript
await client.storeEvent({
graph_id: 'project-x',
event_kind: 'decision',
source: 'user',
context_id: 'intent:refactor',
payload: { topic: 'error_handling', value: 'User wants all unwrap calls replaced with proper error handling' },
});
```
### Retrieve Before Acting
Before executing a task, query the graph for relevant patterns and past errors. This prevents the agent from repeating known mistakes.
```typescript
const context = await client.retrieveMemories({
query: 'auth module errors and fixes',
limit: 5,
contextTypes: { error: ['null_pointer', 'auth_failure'] },
});
```
Always retrieve before acting on files you have edited before. The graph may contain fixes for errors you are about to reintroduce.
### Context Prefix Guide
Use consistent prefixes to organize coding knowledge:
| Prefix | Purpose | Example |
| ---------- | ------------------------- | -------------------- |
| `project:` | Project-level facts | `project:api_server` |
| `error:` | Error patterns and fixes | `error:null_pointer` |
| `file:` | File-specific knowledge | `file:src/auth.rs` |
| `intent:` | User instructions | `intent:refactor` |
| `test:` | Test results and patterns | `test:integration` |
Store the fix alongside the error. When the same error surfaces again, the agent retrieves both the problem and the solution in one query.
### Next
## Memory-Augmented RAG
Combining document retrieval with stored wisdom.
import { Callout } from '../../components/Callout.tsx'
import { LinkCard } from '../../components/link-card.tsx'
import { CodeGroup } from '../../components/code-group.tsx'
### Beyond Standard RAG
Standard RAG retrieves documents. Memory-augmented RAG also retrieves agent experience. The result: context that includes not just what the documents say, but what the agent has learned from working with them.
### The Pattern
Retrieve from two sources, combine in the prompt:
1. **Document retriever** — fetch relevant docs from your vector DB.
2. **Wisdom retriever** — fetch relevant memories from LocusGraph.
3. **Combine** — merge both into the agent's context window.
```typescript
// 1. Retrieve documents (your existing RAG pipeline)
const docs = await vectorDB.search({
query: userQuery,
limit: 5,
});
// 2. Retrieve agent wisdom from LocusGraph
const wisdom = await client.retrieveMemories({
query: userQuery,
limit: 5,
});
// 3. Combine in prompt
const prompt = `
## Relevant Documents
${docs.map(d => d.content).join('\n\n')}
## Agent Knowledge
${wisdom.map(m => m.payload.value).join('\n\n')}
## User Question
${userQuery}
`;
```
### What Wisdom Adds
Documents tell you what exists. Wisdom tells you what works.
| Source | Provides |
| ------------ | ------------------------------------------------------------------------ |
| Documents | API specs, guides, reference material |
| Wisdom graph | Past mistakes, user preferences, learned patterns, successful approaches |
A document might say "use retry logic for network calls." The wisdom graph adds "exponential backoff with a 3-second base works best for this API — linear retry caused rate limiting last week."
LocusGraph's semantic search works alongside any vector database. You do not need to replace your existing RAG pipeline — you augment it.
### Storing RAG Outcomes
Close the loop by storing what the agent learns from each RAG interaction:
```typescript
// After answering, store what worked
await client.storeEvent({
graph_id: 'support-bot',
event_kind: 'observation',
source: 'agent',
context_id: 'rag:effectiveness',
payload: { topic: 'query_pattern', value: 'Users asking about auth need both the setup guide and the troubleshooting doc' },
});
```
Over time, the wisdom graph learns which document combinations answer which question types. RAG gets smarter with every interaction.
### Next
## Multi-Agent Collaboration
Shared graphs, scoped contexts, agent-to-agent knowledge.
import { Callout } from '../../components/Callout.tsx'
import { LinkCard } from '../../components/link-card.tsx'
import { CodeGroup } from '../../components/code-group.tsx'
### Shared Graph, Scoped Contexts
Multiple agents share a single LocusGraph. Each agent reads and writes to the same graph, but uses its own context prefix to organize its knowledge. This gives every agent access to the full wisdom graph while keeping contributions traceable.
### Context Prefixes by Role
Assign each agent a context prefix that reflects its role:
* `agent:planner` — high-level plans, decisions, priorities
* `agent:coder` — implementation details, code patterns, errors
* `agent:reviewer` — review feedback, quality observations
* `agent:tester` — test results, coverage gaps, flaky tests
Shared contexts like `project:api` or `decision:architecture` let agents communicate through stored knowledge.
### How Agents Collaborate
The pattern is simple: one agent stores, another retrieves.
```typescript
// Planner stores a decision
await client.storeEvent({
graph_id: 'team-project',
event_kind: 'decision',
source: 'planner',
context_id: 'agent:planner',
payload: { topic: 'auth_approach', value: 'Use JWT with refresh tokens, 15-minute expiry' },
});
// Coder retrieves planner decisions before implementing
const decisions = await client.retrieveMemories({
query: 'authentication design decisions',
limit: 5,
contextTypes: { agent: ['planner'] },
});
```
The `contextTypes` filter scopes retrieval to specific context prefixes. The coder retrieves only planner decisions without wading through its own past events.
Use `contextTypes` to filter by role. An agent that retrieves everything gets noise. An agent that retrieves from the right contexts gets signal.
### Cross-Agent Knowledge Flow
A typical multi-agent flow:
1. **Planner** stores task breakdowns and architectural decisions.
2. **Coder** retrieves decisions, implements, stores code patterns and errors encountered.
3. **Reviewer** retrieves code patterns and implementation notes, stores review feedback.
4. **Planner** retrieves review feedback and error patterns, adjusts future plans.
Each agent improves the shared graph. The wisdom compounds across all agents, not just within one.
Keep context prefixes consistent across sessions. Changing prefixes fragments the graph and breaks retrieval.
### Next
## Workflows Overview
How agents use LocusGraph in practice.
import { Callout } from '../../components/Callout.tsx'
import { LinkCard } from '../../components/link-card.tsx'
### The Core Agent Loop
Every LocusGraph-powered agent follows the same loop:
1. **Observe** — perceive the environment, user input, or system state.
2. **Store** — record observations, decisions, and actions as events in the wisdom graph.
3. **Retrieve** — pull relevant context from the graph before acting.
4. **Act** — execute with the benefit of accumulated knowledge.
5. **Learn** — refine stored wisdom based on outcomes.
This loop runs every session. Over time, the agent builds a wisdom graph that compounds — each session starts smarter than the last.
### How Sessions Work
Every session starts by retrieving relevant context. The agent queries the graph for recent events, known patterns, and past decisions related to the current task. This grounds the agent in what it already knows.
During the session, every meaningful action gets stored as an event. Commands run, files edited, errors encountered, decisions made — all become nodes in the graph.
At session end, the agent summarizes what happened and links key learnings to persistent contexts. Ephemeral details fade; durable wisdom persists.
### Choosing a Workflow
Different agent architectures call for different workflows:
* **Single agent** — one agent, one graph, persistent wisdom across sessions. The simplest starting point.
* **Multi-agent** — multiple agents share a graph, each with scoped contexts. Agents collaborate through stored knowledge.
* **Memory-augmented RAG** — combine document retrieval with agent experience for richer context.
* **Session and long-term** — manage the lifecycle of ephemeral session data and persistent knowledge.
* **Coding agent** — specialized patterns for terminal commands, file edits, error tracking, and user intent.
Start with the single agent workflow. Add multi-agent coordination or RAG augmentation as your system grows.
### Next
## Session & Long-Term Memory
Managing session lifecycle and persistent wisdom.
import { Callout } from '../../components/Callout.tsx'
import { LinkCard } from '../../components/link-card.tsx'
import { CodeGroup } from '../../components/code-group.tsx'
### Two Tiers of Knowledge
LocusGraph operates on two tiers:
* **Session memory** — ephemeral events tied to a single session. Useful for tracking what happened, but not all of it needs to persist.
* **Long-term wisdom** — durable facts, skills, and patterns that persist across all sessions. This is the compounding value.
### Session Lifecycle
#### 1. Start
Create a session context with a unique identifier.
```typescript
const sessionId = `session:${Date.now().toString(36)}`;
```
#### 2. Observe
Store events tagged with the session context as work progresses.
```typescript
await client.storeEvent({
graph_id: 'default',
event_kind: 'observation',
context_id: 'session:2025_03_19',
payload: { topic: 'debugging', value: 'Found race condition in auth middleware' },
});
```
#### 3. Summarize and Graduate
At session end, extract durable knowledge and store it under permanent contexts. Use `extends` to link the new knowledge back to the session it came from.
```typescript
await client.storeEvent({
graph_id: 'default',
event_kind: 'fact',
context_id: 'skill:concurrency',
extends: ['session:2025_03_19'],
payload: { topic: 'race_condition_fix', value: 'Use mutex guards around shared auth state' },
});
```
The session observation stays in the graph for traceability. The graduated fact lives under `skill:concurrency` and surfaces in future retrievals about concurrency — regardless of session.
Not every session event deserves graduation. Store session events generously, but graduate only the knowledge that will matter next week.
### What Graduates
| Session Event | Graduates To |
| --------------------------------- | ------------------------------------------------------------------------ |
| "Found race condition in auth" | `skill:concurrency` — "Use mutex guards around shared auth state" |
| "User prefers verbose logging" | `preference:logging` — "Enable verbose logging by default" |
| "Retry logic fixed timeout issue" | `skill:error_handling` — "Exponential backoff with 3s base for this API" |
### Retrieval Across Tiers
Retrieve from both tiers in a single query. Long-term facts rank higher by default because they have been validated across sessions.
```typescript
const context = await client.retrieveMemories({
query: 'concurrency patterns for auth',
limit: 10,
});
// Returns both session observations and long-term facts, ranked by relevance
```
Use `contextTypes` to retrieve only long-term knowledge (`skill`, `fact`, `preference`) or only session data (`session`) depending on the task.
### Next
## Single Agent Loop
One agent, persistent wisdom across sessions.
import { Callout } from '../../components/Callout.tsx'
import { LinkCard } from '../../components/link-card.tsx'
import { CodeGroup } from '../../components/code-group.tsx'
### The Simplest Pattern
The single agent loop is the foundation of every LocusGraph workflow: one agent, one graph. The agent stores what it learns and retrieves what it needs. Each session builds on the last.
### Session Start: Retrieve Context
Begin every session by pulling recent context from the graph. A broad query surfaces the most relevant prior knowledge.
### During Session: Store Events
As the agent observes, decides, and acts, store each meaningful event. Tag events with descriptive contexts so they can be retrieved later.
### Session End: Summarize
Close the session by storing a summary event. This captures the session's key outcomes in a single retrievable node.
### Full Example
```typescript
const client = new LocusGraphClient({ graphId: 'my-project' });
// Session start — retrieve recent context
const context = await client.retrieveMemories({
query: 'recent work and decisions',
limit: 10,
});
// During work — store what you learn
await client.storeEvent({
graph_id: 'my-project',
event_kind: 'fact',
source: 'agent',
context_id: 'skill:error_handling',
payload: { topic: 'retry_pattern', value: 'Use exponential backoff for network errors' },
});
// Session end — summarize
await client.storeEvent({
graph_id: 'my-project',
event_kind: 'observation',
source: 'agent',
context_id: 'session:2025_03_19',
payload: { topic: 'session_summary', value: 'Refactored error handling to use exponential backoff' },
});
```
The `context_id` field is how you organize knowledge. Use prefixes like `skill:`, `session:`, or `project:` to create a natural taxonomy.
### What Gets Stored
Focus on events that compound over time:
* **Facts** — durable knowledge the agent discovers (e.g., "this API requires auth headers").
* **Observations** — patterns noticed during work (e.g., "tests fail when DB migrations are pending").
* **Decisions** — choices made and why (e.g., "chose REST over gRPC for simplicity").
* **Summaries** — session-level recaps that anchor future retrieval.
### Next
## FAQ & Troubleshooting
Direct answers to the most common LocusGraph questions.
import { Callout } from '../../components/Callout.tsx'
import { LinkCard } from '../../components/link-card.tsx'
### General
#### How do I get an agent secret?
Sign up at [locusgraph.com](https://locusgraph.com) and create an agent from the dashboard. Each agent receives a unique secret.
#### What is the difference between a graph and a context?
A graph is an isolated workspace -- like a database. A context is a label within a graph -- like a table. One graph can hold thousands of contexts.
#### Can multiple agents share the same graph?
Yes. Use different context prefixes per agent role (e.g., `agent:planner`, `agent:coder`) and filter with `context_types` during retrieval.
### Storing Knowledge
#### Why was my event filtered?
LocusGraph's admission pipeline filters routine and noise events. Events with kind `routine`, `heartbeat`, `status`, `noise`, `debug`, or `log` are typically filtered. Use `fact`, `action`, `decision`, `observation`, or `feedback` instead.
#### Is there a size limit for payloads?
Yes -- 256KB per event payload. Keep payloads focused and flat.
#### What happens when two pieces of knowledge contradict each other?
The `contradicts` link reduces the target's confidence by 0.10 (floor 0.2). Lower-confidence knowledge ranks lower in retrieval results. The newer information effectively overrides the old.
### Retrieving Knowledge
#### How do I scope retrieval to specific knowledge?
Use the `context_ids` or `context_types` filters in `retrieve_memories`. Example:
```typescript
contextTypes: { skill: ["react", "typescript"] }
```
This retrieves only from those specific contexts.
### Connectivity
#### The SDK cannot connect -- what do I check?
Run through this checklist in order. Most connection issues are resolved by step 1.
1. `LOCUSGRAPH_AGENT_SECRET` is set and valid.
2. `LOCUSGRAPH_SERVER_URL` is correct (default: `https://api.locusgraph.com`).
3. Your network or firewall allows outbound HTTPS on port 443.
### Next
import { Callout } from '../../components/Callout.tsx'
import { LinkCard } from '../../components/link-card.tsx'
import { CodeGroup } from '../../components/code-group.tsx'
## Python SDK
The official Python client for LocusGraph — store events, retrieve knowledge, and generate insights from your wisdom graph.
### Installation
```bash
pip install locusgraph-client
# With LangChain support:
pip install locusgraph-client[langchain]
```
### Configuration
```python
from locusgraph_client import LocusGraphClient
client = LocusGraphClient(
server_url="https://api.locusgraph.com", # optional, default
agent_secret="your-agent-secret",
graph_id="default", # optional default graph
)
```
Set `LOCUSGRAPH_SERVER_URL` and `LOCUSGRAPH_AGENT_SECRET` as environment variables to avoid hardcoding credentials. The client reads these automatically when no explicit values are provided.
### Store Event
Add knowledge to your wisdom graph with `store_event`.
```python
response = client.store_event({
"graph_id": "default",
"event_kind": "fact",
"source": "onboarding-flow",
"context_id": "user-preferences",
"payload": "User prefers dark mode and weekly email digests.",
"reinforces": ["ctx-abc123"],
"extends": [],
"contradicts": [],
"related_to": ["ctx-def456"],
"timestamp": "2025-01-15T10:30:00Z",
})
# StoreEventResponse
# response.event_id -> "evt-789"
# response.context_id -> "user-preferences"
# response.status -> "stored"
```
### Retrieve Knowledge
Run semantic search across your wisdom graph with `retrieve_memories`.
```python
result = client.retrieve_memories(
query="What are the user notification preferences?",
graph_id="default",
limit=5,
context_ids=["user-preferences"],
context_types=["fact", "decision"],
)
# ContextResult
# result.memories -> [
# { context_id: "user-preferences", content: "...", score: 0.92, ... }
# ]
```
### Get Context
Fetch a single context by ID. Raises `RuntimeError("Context not found")` on 404.
```python
try:
context = client.get_context(
context_id="user-preferences",
graph_id="default",
)
# GetContextResponse
# context.context_id -> "user-preferences"
# context.context_type -> "fact"
# context.content -> "User prefers dark mode..."
except RuntimeError as e:
print(e) # "Context not found"
```
### List Contexts
Browse, filter, and search contexts in your wisdom graph.
#### List context types
```python
types = client.list_context_types(
graph_id="default",
page=0,
page_size=100,
)
# ContextTypesResponse
# types.context_types -> ["fact", "action", "decision", ...]
```
#### List contexts by type
```python
facts = client.list_contexts_by_type(
context_type="fact",
graph_id="default",
page=0,
page_size=50,
)
# ContextListResponse
# facts.contexts -> [{ context_id: "...", content: "...", ... }]
```
#### Search contexts
```python
results = client.search_contexts(
query="preferences",
graph_id="default",
limit=10,
)
# ContextSearchResponse
# results.contexts -> [...]
```
### Get Context Relationships
Explore how contexts connect within your wisdom graph.
```python
relationships = client.get_context_relationships(
context_type="fact",
context_name="user-preferences",
graph_id="default",
)
# ContextRelationshipsResponse
# relationships.reinforced_by -> [...]
# relationships.extended_by -> [...]
# relationships.contradicted_by -> [...]
```
### Generate Insights
Reason over your wisdom graph to produce synthesized answers.
```python
insight = client.generate_insights(
task="Summarize user preferences and suggest personalization strategies.",
graph_id="default",
locus_query="user preferences and settings",
limit=10,
context_ids=["user-preferences"],
context_types=["fact", "decision"],
)
# InsightResult
# insight.insight -> "Based on stored knowledge, the user prefers..."
# insight.sources -> ["ctx-abc123", "ctx-def456"]
# insight.confidence -> 0.89
```
### Environment Variables
| Variable | Description |
| ------------------------- | ------------------------------------------------------ |
| `LOCUSGRAPH_SERVER_URL` | API server URL (default: `https://api.locusgraph.com`) |
| `LOCUSGRAPH_AGENT_SECRET` | Your agent secret key |
### Next
import { Callout } from '../../components/Callout.tsx'
import { LinkCard } from '../../components/link-card.tsx'
## Rust SDK
The official Rust client for LocusGraph — store events, retrieve knowledge, and generate insights from your wisdom graph.
### Installation
Add the dependency to your `Cargo.toml`:
```toml
[dependencies]
locusgraph-client = "0.1"
```
### Configuration
```rust
use locusgraph_client::{LocusGraphClient, LocusGraphConfig};
let config = LocusGraphConfig {
server_url: Some("https://api.locusgraph.com".to_string()),
agent_secret: Some("your-agent-secret".to_string()),
graph_id: Some("default".to_string()),
};
let client = LocusGraphClient::new(Some(config));
```
Set `LOCUSGRAPH_SERVER_URL` and `LOCUSGRAPH_AGENT_SECRET` as environment variables to avoid hardcoding credentials. The client reads these automatically when config values are `None`.
The Rust SDK uses a blocking HTTP API powered by `ureq`. All methods block the current thread until the response arrives.
### Store Event
Add knowledge to your wisdom graph with `store_event`.
```rust
use locusgraph_client::CreateEventRequest;
let request = CreateEventRequest {
graph_id: "default".to_string(),
event_kind: "fact".to_string(),
source: Some("onboarding-flow".to_string()),
context_id: Some("user-preferences".to_string()),
payload: "User prefers dark mode and weekly email digests.".to_string(),
reinforces: Some(vec!["ctx-abc123".to_string()]),
extends: None,
contradicts: None,
related_to: Some(vec!["ctx-def456".to_string()]),
timestamp: Some("2025-01-15T10:30:00Z".to_string()),
};
let response = client.store_event(request)?;
// response.event_id -> "evt-789"
// response.context_id -> "user-preferences"
// response.status -> "stored"
```
### Retrieve Knowledge
Run semantic search across your wisdom graph with `retrieve_memories`.
```rust
let result = client.retrieve_memories(
"default", // graph_id
"What are the user notification preferences?", // query
Some(5), // limit
Some(vec!["user-preferences".to_string()]), // context_ids
Some(vec!["fact".to_string()]), // context_types
)?;
// result.memories -> Vec
// result.memories[0].content -> "User prefers weekly email digests."
// result.memories[0].score -> 0.92
// result.memories[0].context_type -> "fact"
```
### Get Context
Fetch a single context by ID. Returns an error if the context does not exist.
```rust
let context = client.get_context(
"user-preferences", // context_id
"default", // graph_id
)?;
// context.context_id -> "user-preferences"
// context.context_type -> "fact"
// context.content -> "User prefers dark mode..."
```
### List Context Types
Browse available context types in your wisdom graph.
```rust
let types = client.list_context_types(
"default", // graph_id
0, // page
100, // page_size
)?;
// types.context_types -> vec!["fact", "action", "decision", ...]
```
### Generate Insights
Reason over your wisdom graph and produce synthesized answers.
```rust
let insight = client.generate_insights(
"default", // graph_id
"Summarize user preferences and suggest personalization strategies.", // task
Some("user preferences and settings".to_string()), // locus_query
Some(10), // limit
Some(vec!["user-preferences".to_string()]), // context_ids
Some(vec!["fact".to_string(), "decision".to_string()]), // context_types
)?;
// insight.insight -> "Based on stored knowledge, the user prefers..."
// insight.sources -> vec!["ctx-abc123", "ctx-def456"]
// insight.confidence -> 0.89
```
### Environment Variables
| Variable | Description |
| ------------------------- | ------------------------------------------------------ |
| `LOCUSGRAPH_SERVER_URL` | API server URL (default: `https://api.locusgraph.com`) |
| `LOCUSGRAPH_AGENT_SECRET` | Your agent secret key |
### Next
import { Callout } from '../../components/Callout.tsx'
import { LinkCard } from '../../components/link-card.tsx'
import { CodeGroup } from '../../components/code-group.tsx'
## TypeScript SDK
The official TypeScript client for LocusGraph — store events, retrieve knowledge, and generate insights from your wisdom graph.
### Installation
```bash
npm install @locusgraph/client
```
### Configuration
```typescript
import { LocusGraphClient } from '@locusgraph/client';
const client = new LocusGraphClient({
serverUrl: 'https://api.locusgraph.com', // optional, default
agentSecret: 'your-agent-secret',
graphId: 'default', // optional default graph
});
```
Set `LOCUSGRAPH_SERVER_URL` and `LOCUSGRAPH_AGENT_SECRET` as environment variables to avoid hardcoding credentials. The client reads these automatically when no explicit values are provided.
### Store Event
Use `storeEvent` to add knowledge to your wisdom graph. Each event captures a fact, action, decision, or observation.
```typescript
const response = await client.storeEvent({
graph_id: 'default',
event_kind: 'fact',
source: 'onboarding-flow',
context_id: 'user-preferences',
payload: 'User prefers dark mode and weekly email digests.',
reinforces: ['ctx-abc123'],
extends: [],
contradicts: [],
related_to: ['ctx-def456'],
timestamp: '2025-01-15T10:30:00Z',
});
// Response
// {
// eventId: 'evt-789',
// contextId: 'user-preferences',
// status: 'stored'
// }
```
| Field | Required | Description |
| ------------- | -------- | ------------------------------------------------------------------- |
| `graph_id` | Yes | Target graph identifier |
| `event_kind` | Yes | Event type: `fact`, `action`, `decision`, `observation`, `feedback` |
| `payload` | Yes | The knowledge content |
| `source` | No | Origin of the event |
| `context_id` | No | Group events under a context |
| `reinforces` | No | Array of context IDs this event reinforces |
| `extends` | No | Array of context IDs this event extends |
| `contradicts` | No | Array of context IDs this event contradicts |
| `related_to` | No | Array of related context IDs |
| `timestamp` | No | ISO 8601 timestamp string |
### Retrieve Knowledge
Use `retrieveMemories` to run semantic search across your wisdom graph.
```typescript
const result = await client.retrieveMemories({
graphId: 'default',
query: 'What are the user preferences for notifications?',
limit: 5,
contextIds: ['user-preferences'],
contextTypes: ['fact', 'decision'],
});
// Response
// {
// memories: [
// {
// contextId: 'user-preferences',
// content: 'User prefers weekly email digests.',
// score: 0.92,
// contextType: 'fact',
// timestamp: '2025-01-15T10:30:00Z'
// }
// ]
// }
```
| Field | Required | Description |
| -------------- | -------- | ----------------------------------- |
| `graphId` | No | Uses default from config if omitted |
| `query` | Yes | Natural language search query |
| `limit` | No | Max results to return |
| `contextIds` | No | Filter by specific context IDs |
| `contextTypes` | No | Filter by context types |
### Get Context
Fetch a single context by its ID. Throws `Error('Context not found')` on 404.
```typescript
try {
const context = await client.getContext({
context_id: 'user-preferences',
graph_id: 'default',
});
// Response
// {
// contextId: 'user-preferences',
// contextType: 'fact',
// content: 'User prefers dark mode and weekly email digests.',
// createdAt: '2025-01-15T10:30:00Z',
// updatedAt: '2025-01-15T10:30:00Z'
// }
} catch (err) {
console.error(err.message); // 'Context not found'
}
```
### List Contexts
Browse context types, list contexts by type, or search by name.
```typescript
// List all context types
const types = await client.listContexts({ graph_id: 'default' });
// List contexts by type
const facts = await client.listContexts({
graph_id: 'default',
context_type: 'fact',
});
// Search contexts by name
const results = await client.listContexts({
graph_id: 'default',
query: 'preferences',
});
```
### Generate Insights
Use `generateInsights` to reason over your wisdom graph and produce synthesized answers.
```typescript
const insight = await client.generateInsights({
graphId: 'default',
task: 'Summarize this user preferences and suggest personalization strategies.',
locusQuery: 'user preferences and settings',
limit: 10,
contextIds: ['user-preferences'],
contextTypes: ['fact', 'decision'],
});
// Response
// {
// insight: 'Based on stored knowledge, the user prefers dark mode...',
// sources: ['ctx-abc123', 'ctx-def456'],
// confidence: 0.89
// }
```
| Field | Required | Description |
| -------------- | -------- | ------------------------------------------ |
| `graphId` | No | Uses default from config if omitted |
| `task` | Yes | The reasoning task or question |
| `locusQuery` | No | Optional query to scope relevant knowledge |
| `limit` | No | Max source contexts to consider |
| `contextIds` | No | Filter by specific context IDs |
| `contextTypes` | No | Filter by context types |
### Environment Variables
| Variable | Description |
| ------------------------- | ------------------------------------------------------ |
| `LOCUSGRAPH_SERVER_URL` | API server URL (default: `https://api.locusgraph.com`) |
| `LOCUSGRAPH_AGENT_SECRET` | Your agent secret key |
### Next
## Claude Code
Connect Claude Code to LocusGraph over MCP using the production auth endpoint:
```text
https://api.locusgraph.com/mcp
```
import { Callout } from '../../components/Callout.tsx'
import { CodeGroup } from '../../components/code-group.tsx'
import { LinkCard } from '../../components/link-card.tsx'
Claude Code supports remote HTTP MCP servers and uses `/mcp` for OAuth authentication. This guide follows Anthropic's Claude Code MCP documentation for remote HTTP transport, configuration scopes, and OAuth behavior.
Official reference: [Connect Claude Code to tools via MCP](https://code.claude.com/docs/en/mcp)
### Add LocusGraph
HTTP is the recommended transport for remote cloud-hosted MCP services. Add LocusGraph with one of these commands:
```bash
claude mcp add --transport http locusgraph https://api.locusgraph.com/mcp
```
```bash
claude mcp add --transport http --scope project locusgraph https://api.locusgraph.com/mcp
```
```bash
claude mcp add --transport http --scope user locusgraph https://api.locusgraph.com/mcp
```
Scope choice:
* `local`: private to your current project on your machine
* `project`: shared via `.mcp.json` at the repo root
* `user`: available across your projects on your machine
Use `--scope project` when the whole team should see the same LocusGraph MCP server in the repo. Claude Code will create or update `.mcp.json`.
### Authenticate
LocusGraph uses OAuth at `https://api.locusgraph.com/mcp`. After adding the server:
1. Open Claude Code in the project where you want to use LocusGraph.
2. Run `/mcp`.
3. Select `locusgraph`.
4. Choose Authenticate if Claude Code shows the server as unauthenticated.
5. Finish the browser login flow, then select the graph you want to bind to the token.
6. Return to Claude Code and run `/mcp` again to confirm the server is connected.
Once connected, Claude Code should discover:
* `store_event`
* `retrieve_memories`
* `list_contexts`
* `generate_insights`
* `locusgraph://contexts`
* `auto_capture`
LocusGraph's production auth worker supports dynamic client registration, so the standard Claude Code OAuth flow should work without manually supplying `--client-id` or `--client-secret`.
### Shared `.mcp.json`
Project scope writes a repo-level `.mcp.json`. A minimal LocusGraph entry looks like this:
```json
{
"mcpServers": {
"locusgraph": {
"type": "http",
"url": "https://api.locusgraph.com/mcp"
}
}
}
```
Claude Code asks for approval before using project-scoped servers from `.mcp.json`. That is expected behavior for shared repo config.
### Fixed Callback Port
Claude Code can use a fixed localhost callback port when a server or organization requires a pre-registered redirect URI such as `http://localhost:8765/callback`.
```bash
claude mcp add --transport http --callback-port 8765 locusgraph https://api.locusgraph.com/mcp
```
For the default `api.locusgraph.com` setup, this is usually not required. Use it only if your OAuth setup depends on a specific localhost callback port.
### Verify
You can verify the server from the CLI and inside Claude Code:
```bash
claude mcp list
claude mcp get locusgraph
```
Then inside Claude Code:
```text
/mcp
```
If authentication completed correctly, Claude Code should show the server as connected and make the MCP tools available in-session.
### Troubleshooting
| Problem | Fix |
| ------------------------------------------- | ------------------------------------------------------------------------------ |
| Claude Code shows `Authentication required` | Run `/mcp`, select `locusgraph`, and complete the browser OAuth flow |
| Browser does not open automatically | Copy the auth URL from Claude Code and open it manually in the browser |
| Redirect fails after login | Paste the full callback URL from the browser back into Claude Code if prompted |
| Team members do not see the server | Use `--scope project` or commit the repo's `.mcp.json` |
| Tools are missing after auth | Reopen `/mcp` or restart the Claude Code session so capabilities refresh |
### Next
## Connecting MCP Clients
Connect any MCP client that supports remote HTTP MCP plus OAuth 2.0 discovery.
import { Steps, Step } from '../../components/step.tsx'
import { Callout } from '../../components/Callout.tsx'
import { CodeGroup } from '../../components/code-group.tsx'
import { LinkCard } from '../../components/link-card.tsx'
### Setup
You connect to the auth worker, not directly to a region server. The MCP endpoint is:
```text
https://api.locusgraph.com/mcp
```
The same auth worker also serves OAuth discovery:
```text
https://api.locusgraph.com/.well-known/oauth-protected-resource
https://api.locusgraph.com/.well-known/oauth-authorization-server
https://api.locusgraph.com/.well-known/openid-configuration
```
Configure your client to use the remote `/mcp` endpoint above. Do not point the client at a local `npx @locusgraph/mcp-server` command unless you intentionally maintain a separate stdio wrapper.
```text
MCP endpoint: https://api.locusgraph.com/mcp
Protected resource: https://api.locusgraph.com/.well-known/oauth-protected-resource
Authorization: OAuth 2.0 authorization code flow
```
```bash
OAUTH_REDIRECT_URL=https://api.locusgraph.com
MCP_OAUTH_CLIENT_ID=...
MCP_OAUTH_CLIENT_SECRET=...
MCP_OAUTH_REDIRECT_URIS=https://chat.openai.com/aip/callback
MCP_OAUTH_SCOPES=profile memory.read memory.write
OPENAI_APPS_CHALLENGE=...
```
When the client connects, the auth worker returns OAuth metadata and the client completes the authorization code flow:
1. The client discovers metadata from `/.well-known/oauth-protected-resource`
2. It registers dynamically at `/oauth/register`, or uses a preconfigured static client
3. The user signs in at `/oauth/authorize`
4. The user selects a graph
5. The auth worker returns an access token bound to that graph
Ask your client to:
1. initialize the MCP session
2. list tools
3. list resources
4. list prompts
You should see the four tools, the `locusgraph://contexts` resource, and the `auto_capture` prompt.
The auth worker accepts both dynamic OAuth clients and an env-managed static client. Static client credentials are configured with `MCP_OAUTH_CLIENT_ID`, `MCP_OAUTH_CLIENT_SECRET`, and `MCP_OAUTH_REDIRECT_URIS`.
The production auth base URL is `https://api.locusgraph.com`.
### Client-Specific Guides
Use the dedicated Claude Code page for the full remote HTTP, OAuth, scope, and `.mcp.json` setup flow:
### Static Client Helper
For ChatGPT or any deployment where you want a fixed OAuth client, generate credentials from the auth app:
```bash
cd apps/auth
./scripts/generate-mcp-client.sh chatgpt-locusgraph-prod
```
Set the printed values in your Worker secrets/config, then add the exact redirect URI your MCP client provides.
### Required Auth Worker Configuration
| Variable | Required | Purpose |
| ------------------------- | -------- | ------------------------------------------------------------ |
| `OAUTH_REDIRECT_URL` | Yes | Public base URL of the auth worker |
| `MCP_OAUTH_CLIENT_ID` | No | Static OAuth client ID for env-managed clients |
| `MCP_OAUTH_CLIENT_SECRET` | No | Static OAuth client secret |
| `MCP_OAUTH_REDIRECT_URIS` | No | Comma-separated allowed callback URIs |
| `MCP_OAUTH_SCOPES` | No | OAuth scopes; defaults to `profile memory.read memory.write` |
| `OPENAI_APPS_CHALLENGE` | No | OpenAI Apps verification challenge file |
| `LOCUSGRAPH_SERVER_URL` | No | Region server override for local development |
### Redirect URI Rules
The auth worker accepts redirect URIs that are:
* `https://...`
* loopback `http://localhost...` or `http://127.0.0.1...`
* a valid custom native-app scheme such as `myapp://callback`
It rejects browser-executable schemes such as `javascript:`, `data:`, or `file:`.
The current auth worker is OAuth-based MCP. The older agent-secret examples are stale for this deployment path.
### Troubleshooting
| Problem | Fix |
| ----------------------------------------- | ------------------------------------------------------------------------ |
| `401 Authentication required` from `/mcp` | Complete the OAuth flow first. Only `initialize` is unauthenticated. |
| `invalid_target` during OAuth | Use the auth worker's `/mcp` resource URL, not the region server URL. |
| Public client rejected | Public clients must use PKCE with `code_challenge_method=S256`. |
| MCP calls fail with missing graph access | Select a graph during `/oauth/authorize`; issued tokens are graph-bound. |
| Redirect URI rejected | Use HTTPS, loopback HTTP, or a valid native-app custom scheme. |
### Next
## Model Context Protocol (MCP)
MCP is an open protocol that lets AI agents connect to external tools and data sources. In LocusGraph, MCP is served through the auth worker as a remote OAuth-protected endpoint.
import { Callout } from '../../components/Callout.tsx'
import { LinkCard } from '../../components/link-card.tsx'
### What is MCP?
Model Context Protocol standardizes how AI agents discover and call external tools. Instead of writing custom integrations for each agent framework, you expose a single MCP server. Any compatible client connects instantly.
MCP defines three primitives:
* **Tools** — functions the agent can call (store knowledge, retrieve wisdom, generate insights)
* **Resources** — read-only data the agent can browse before calling tools
* **Prompts** — reusable prompt templates the client can fetch on demand
### Why MCP for LocusGraph?
LocusGraph exposes its memory workflows over MCP at the auth worker's `/mcp` endpoint. The auth worker handles OAuth, binds the token to a selected graph, and then proxies MCP calls into the region server.
The backend currently exposes:
* Four tools: `store_event`, `retrieve_memories`, `list_contexts`, `generate_insights`
* One resource: `locusgraph://contexts`
* One prompt: `auto_capture`
Use MCP when your client supports remote HTTP MCP with OAuth 2.0. Use the SDKs when you want direct application-level control.
### How It Works
1. Your MCP client connects to `https://api.locusgraph.com/mcp`.
2. The auth worker challenges the client with OAuth metadata from `/.well-known/oauth-protected-resource`.
3. The client discovers the authorization server at `/.well-known/oauth-authorization-server` and `/.well-known/openid-configuration`.
4. The user signs in, approves access, and selects a graph during `/oauth/authorize`.
5. The auth worker issues an OAuth token with scopes such as `profile`, `memory.read`, and `memory.write`.
6. Each authenticated MCP request is proxied to the region server with the selected graph injected via `X-Graph-Id`.
### Auth Endpoints
The auth worker exposes these MCP-related endpoints:
| Endpoint | Purpose |
| --------------------------------------------- | --------------------------------------------- |
| `POST /mcp` | Remote MCP endpoint |
| `GET /.well-known/oauth-protected-resource` | Protected resource metadata for `/mcp` |
| `GET /.well-known/oauth-authorization-server` | OAuth authorization server metadata |
| `GET /.well-known/openid-configuration` | OpenID configuration |
| `GET /oauth/authorize` | Authorization UI and graph selection |
| `POST /oauth/register` | Dynamic client registration |
| `POST /oauth/token` | Authorization code and refresh token exchange |
| `GET /oauth/userinfo` | User claims for issued access tokens |
The production auth host is `https://api.locusgraph.com`.
### Next
## MCP Resources
MCP resources expose read-only graph data for browsing without making tool calls.
import { Callout } from '../../components/Callout.tsx'
import { LinkCard } from '../../components/link-card.tsx'
### What Are Resources?
Resources are read-only data endpoints that MCP clients can discover and read. Unlike tools, resources do not modify state. They let agents browse the graph structure before deciding what to query.
LocusGraph currently exposes one resource via `resources/list`.
### Available Resource
**URI:** `locusgraph://contexts`
This resource returns the contexts linked into the selected graph. Each item includes:
* `context_id`
* `reference_count`
### Example `resources/read`
```json
{
"jsonrpc": "2.0",
"id": 1,
"method": "resources/read",
"params": {
"uri": "locusgraph://contexts"
}
}
```
Resources are graph-scoped. The auth worker injects the selected graph into the proxied MCP request, so `resources/read` operates on the graph chosen during OAuth authorization.
### When to Use Resources vs. Tools
| Use Case | Approach |
| --------------------------------------------------- | ------------------------------------- |
| Browse what context IDs exist in the selected graph | Read resources |
| Search for specific wisdom | Call `retrieve_memories` tool |
| Store new knowledge | Call `store_event` tool |
| Explore before filtering tools | Read resources, then query with tools |
Resources are best for orientation. Tools are best for action.
### Prompts
The same MCP surface also exposes one prompt through `prompts/list` and `prompts/get`:
* `auto_capture` — a reusable prompt that instructs the client to store new knowledge immediately with `store_event`
### Next
## MCP Tools
LocusGraph currently exposes four MCP tools through the region server, with OAuth enforced at the auth worker's `/mcp` endpoint.
import { Callout } from '../../components/Callout.tsx'
import { LinkCard } from '../../components/link-card.tsx'
### Scopes
OAuth scopes are enforced before the request reaches the graph:
| Tool | Required scopes |
| ------------------- | ----------------------------- |
| `retrieve_memories` | `memory.read` |
| `list_contexts` | `memory.read` |
| `store_event` | `memory.read`, `memory.write` |
| `generate_insights` | `memory.read`, `memory.write` |
The access token is also bound to the selected `graph_id`, and the auth worker forwards that graph to the region server via `X-Graph-Id`.
### store\_event
Writes knowledge into the wisdom graph. The admission pipeline processes the event into a locus automatically.
**Parameters:**
| Name | Required | Description |
| ------------- | -------- | ----------------------------------------------------------------------------------- |
| `event_kind` | Yes | Event kind: `fact`, `action`, `decision`, `observation`, `feedback` |
| `payload` | No | Memory payload. Recommended shape: `{ "data": { "topic": "...", "value": "..." } }` |
| `context_id` | No | Primary context in format `type:name` |
| `source` | No | Event source: `agent`, `user`, `system`, `validator`, `executor` |
| `reinforces` | No | Array of context IDs this event reinforces |
| `extends` | No | Array of context IDs this event extends |
| `contradicts` | No | Array of context IDs this event contradicts |
| `related_to` | No | Array of related context IDs |
| `timestamp` | No | Unix timestamp as string |
Aliases accepted by the backend:
* `context_id`: also accepts `event_id`
* `event_kind`: also accepts `event_type` and `eventType`
* `payload`: also accepts `content`
```json
{
"tool": "store_event",
"arguments": {
"context_id": "skill:react_hooks",
"event_kind": "fact",
"source": "agent",
"payload": {
"topic": "useEffect cleanup", "value": "Always return a cleanup function when subscribing to external stores"
}
}
}
```
### retrieve\_memories
Searches the wisdom graph using semantic similarity and returns ranked results.
**Parameters:**
| Name | Required | Description |
| --------------- | -------- | ------------------------------------------------- |
| `query` | Yes | Search query string |
| `limit` | No | Maximum number of results |
| `context_ids` | No | Filter by specific context IDs |
| `context_types` | No | Filter by context types (map of type to names) |
| `include_ids` | No | Include locus IDs and context IDs in the response |
```json
{
"tool": "retrieve_memories",
"arguments": {
"query": "React hook best practices",
"limit": 5,
"context_types": { "skill": ["react_hooks"] }
}
}
```
### list\_contexts
Lists available context IDs with optional filtering and pagination.
**Parameters:**
| Name | Required | Description |
| -------------- | -------- | ----------------------------- |
| `context_type` | No | Filter by context type |
| `context_name` | No | Filter by context name |
| `limit` | No | Max results. Default: `100` |
| `page` | No | Pagination page. Default: `0` |
```json
{
"tool": "list_contexts",
"arguments": {
"context_type": "skill",
"limit": 10
}
}
```
### generate\_insights
Analyzes stored knowledge and generates insights for a given task.
**Parameters:**
| Name | Required | Description |
| --------------- | -------- | --------------------------------------------- |
| `task` | Yes | Task description for insight generation |
| `locus_query` | No | Query for searching relevant knowledge |
| `limit` | No | Maximum number of knowledge items to retrieve |
| `context_ids` | No | Filter by specific context IDs |
| `context_types` | No | Filter by context types |
The backend also accepts `context_query` as an alias for `locus_query`.
```json
{
"tool": "generate_insights",
"arguments": {
"task": "Refactor the authentication module",
"locus_query": "authentication patterns and past errors",
"limit": 10,
"context_types": { "error": [], "skill": [] }
}
}
```
`tools/list` is discoverable over MCP, but `tools/call` uses OAuth access tokens issued by the auth worker, not direct `LOCUSGRAPH_AGENT_SECRET` configuration.
### Next
import { Callout } from '../../components/Callout.tsx'
import { LinkCard } from '../../components/link-card.tsx'
import { CodeGroup } from '../../components/code-group.tsx'
## LangChain Integration
Connect your LocusGraph wisdom graph to LangChain agents with `LocusGraphMemory` and `LocusGraphRetriever`.
### Installation
```bash {{ title: "TypeScript" }}
npm install @locusgraph/client @langchain/core langchain
```
```bash {{ title: "Python" }}
pip install locusgraph-client[langchain]
```
### LocusGraphMemory
`LocusGraphMemory` gives LangChain chains access to your wisdom graph as conversational context. It stores conversation events automatically and retrieves relevant knowledge on each turn.
#### TypeScript
```typescript
import { LocusGraphClient, LocusGraphMemory } from '@locusgraph/client';
import { ConversationChain } from 'langchain/chains';
import { ChatOpenAI } from '@langchain/openai';
const client = new LocusGraphClient({
agentSecret: process.env.LOCUSGRAPH_AGENT_SECRET,
});
const memory = new LocusGraphMemory(
client,
'default', // graphId
'my-agent', // agentId
'session-123', // sessionId
);
const chain = new ConversationChain({
llm: new ChatOpenAI(),
memory,
});
const response = await chain.call({ input: 'What do you know about my preferences?' });
```
#### Python
```python
from locusgraph_client import LocusGraphClient, LocusGraphMemory
from langchain.chains import ConversationChain
from langchain_openai import ChatOpenAI
client = LocusGraphClient(agent_secret="your-secret")
memory = LocusGraphMemory(
client,
"default", # graph_id
agent_id="my-agent",
session_id="session-123",
)
chain = ConversationChain(llm=ChatOpenAI(), memory=memory)
response = chain.invoke({"input": "What do you know about my preferences?"})
```
#### Memory Keys
`LocusGraphMemory` exposes three keys to your chain's prompt:
| Key | Description |
| ------------- | -------------------------------------------------- |
| `history` | Recent conversation turns from the current session |
| `memories` | Relevant knowledge retrieved from the wisdom graph |
| `memory_info` | Metadata about retrieved contexts (scores, types) |
#### Automatic Event Classification
When `LocusGraphMemory` stores conversation events, it classifies them automatically:
| Classification | Trigger |
| -------------- | ----------------------------------------------------------------- |
| `fact` | User states preferences, personal details, or factual information |
| `action` | User requests a task or the agent performs one |
| `decision` | User makes a choice between alternatives |
| `feedback` | User expresses opinions or satisfaction |
| `observation` | Default for all other conversational content |
### LocusGraphRetriever
`LocusGraphRetriever` implements LangChain's retriever interface, letting you plug your wisdom graph into any retrieval chain.
#### TypeScript
```typescript
import { LocusGraphClient, LocusGraphRetriever } from '@locusgraph/client';
import { RetrievalQAChain } from 'langchain/chains';
import { ChatOpenAI } from '@langchain/openai';
const client = new LocusGraphClient({
agentSecret: process.env.LOCUSGRAPH_AGENT_SECRET,
});
const retriever = new LocusGraphRetriever({
client,
graphId: 'default',
limit: 10,
});
const chain = RetrievalQAChain.fromLLM(new ChatOpenAI(), retriever);
const response = await chain.call({ query: 'Summarize user preferences' });
```
#### Python
```python
from locusgraph_client import LocusGraphClient, LocusGraphRetriever
from langchain.chains import RetrievalQA
from langchain_openai import ChatOpenAI
client = LocusGraphClient(agent_secret="your-secret")
retriever = LocusGraphRetriever(
client=client,
graph_id="default",
limit=10,
)
chain = RetrievalQA.from_llm(llm=ChatOpenAI(), retriever=retriever)
response = chain.invoke({"query": "Summarize user preferences"})
```
`LocusGraphRetriever` returns LangChain `Document` objects. Each document's `page_content` holds the context content, and `metadata` includes `context_id`, `context_type`, and `score`.
### Next
## Common Patterns
Proven patterns for building wisdom into your agents with LocusGraph.
import { Callout } from '../../components/Callout.tsx'
import { LinkCard } from '../../components/link-card.tsx'
### Graduation Chains
The most powerful pattern in LocusGraph turns mistakes into skills through three stages: mistake, pattern, skill.
**Step 1: Store a mistake.** When an agent makes an error, record it as an observation with an `error:` context.
```typescript
await client.storeEvent({
graph_id: 'default',
event_kind: 'observation',
source: 'agent',
context_id: 'error:off_by_one',
payload: { topic: 'off_by_one', value: 'Array index out of bounds in pagination logic' },
});
```
**Step 2: Recognize the pattern.** When the same error appears 3+ times, store a pattern that links back to the error context with `reinforces`.
```typescript
await client.storeEvent({
graph_id: 'default',
event_kind: 'fact',
source: 'agent',
context_id: 'pattern:pagination_bounds',
reinforces: ['error:off_by_one'],
payload: { topic: 'pagination_bounds', value: 'Always use length - 1 for zero-indexed arrays' },
});
```
**Step 3: Graduate to skill.** After the pattern proves useful 5+ times, promote it to a skill with `extends`.
```typescript
await client.storeEvent({
graph_id: 'default',
event_kind: 'fact',
source: 'agent',
context_id: 'skill:safe_pagination',
extends: ['pattern:pagination_bounds'],
payload: { topic: 'safe_pagination', value: 'Clamp page index between 0 and Math.ceil(total/pageSize) - 1' },
});
```
The graduation chain lets your agent build durable skills from raw experience. Skills retrieved during future sessions prevent the same mistakes from recurring.
### Preference Tracking
Store user preferences as facts. When the same preference surfaces again, use `reinforces` to link back to the original. This raises its confidence score, ensuring it ranks higher in retrieval results.
### Session Bookends
Bracket each session with a start event and an end event. Tag all events within the session using a consistent `session:` context prefix (e.g., `session:2024-03-15-abc`). This makes it easy to retrieve everything that happened in a given session and to track how the agent's knowledge evolved over time.
### Next
## Environment Variables
Every configuration option available for LocusGraph SDKs.
import { Callout } from '../../components/Callout.tsx'
import { LinkCard } from '../../components/link-card.tsx'
### Reference
| Variable | Required | Default | Description |
| ------------------------- | -------- | ---------------------------- | -------------------------- |
| `LOCUSGRAPH_SERVER_URL` | No | `https://api.locusgraph.com` | API server URL |
| `LOCUSGRAPH_AGENT_SECRET` | Yes | — | Agent authentication token |
### Setting Environment Variables
Create a `.env` file in your project root:
```bash
# .env file
LOCUSGRAPH_SERVER_URL=https://api.locusgraph.com
LOCUSGRAPH_AGENT_SECRET=your-agent-secret
```
Never commit `LOCUSGRAPH_AGENT_SECRET` to version control. Add `.env` to your `.gitignore` immediately.
### Per-Language Usage
**TypeScript** reads from environment automatically, or accepts explicit config:
```typescript
const client = new LocusGraphClient({
serverUrl: process.env.LOCUSGRAPH_SERVER_URL,
agentSecret: process.env.LOCUSGRAPH_AGENT_SECRET,
});
```
**Python** reads from environment automatically, or accepts constructor arguments:
```python
client = LocusGraphClient(
server_url=os.environ.get("LOCUSGRAPH_SERVER_URL"),
agent_secret=os.environ.get("LOCUSGRAPH_AGENT_SECRET"),
)
```
**Rust** reads from environment automatically, or accepts config:
```rust
let client = LocusGraphClient::new(None); // reads from env
```
All three SDKs follow the same priority: explicit config overrides environment variables, which override defaults. If you pass `None` or omit a field, the SDK falls back to the environment variable. If that is unset, it uses the default (for `LOCUSGRAPH_SERVER_URL`) or returns an error (for `LOCUSGRAPH_AGENT_SECRET`).
### Next
## Error Handling
What breaks, why it breaks, and how to handle it across every SDK.
import { Callout } from '../../components/Callout.tsx'
import { LinkCard } from '../../components/link-card.tsx'
import { CodeGroup } from '../../components/code-group.tsx'
### Common Errors
| Status | Meaning | Typical Cause |
| ---------------- | ----------------- | ------------------------------------------------------------------------------------------------- |
| 400 Bad Request | Invalid input | Bad `event_kind`, payload over 256KB, too many link IDs (>100 total), invalid `context_id` format |
| 401 Unauthorized | Auth failure | Missing or invalid `LOCUSGRAPH_AGENT_SECRET` |
| 404 Not Found | Resource missing | Context doesn't exist (when calling `getContext`) |
| 429 Rate Limited | Too many requests | Slow down or batch your calls |
The most common mistake: forgetting to set `LOCUSGRAPH_AGENT_SECRET`. Every SDK call will return 401 until it is configured.
### Handling Errors by Language
**TypeScript:**
```typescript
try {
await client.storeEvent({ ... });
} catch (error) {
if (error instanceof Error) {
console.error('Store failed:', error.message);
}
}
```
**Python:**
```python
try:
client.store_event({...})
except RuntimeError as e:
print(f"Store failed: {e}")
```
**Rust:**
```rust
match client.store_event(request) {
Ok(response) => println!("Stored: {}", response.event_id),
Err(e) => eprintln!("Store failed: {}", e),
}
```
### Validation Constraints
Stay within these limits to avoid 400 errors:
| Constraint | Limit |
| ------------------------------------------------------ | -------------- |
| Event kind max length | 128 characters |
| Context ID max length | 256 characters |
| Link IDs per field (`reinforces`, `contradicts`, etc.) | 50 |
| Total link IDs across all fields | 100 |
| Payload max size | 256KB |
| Batch events max | 100 per call |
If you hit 429 rate limits, switch to batch event storage. One batch call with 50 events is better than 50 individual calls.
### Next
## Authentication
Every request to LocusGraph requires an agent secret passed as a Bearer token.
import { Callout } from '../../components/Callout.tsx'
import { Steps, Step } from '../../components/step.tsx'
import { CodeGroup } from '../../components/code-group.tsx'
import { LinkCard } from '../../components/link-card.tsx'
import { Badge } from '../../components/badge.tsx'
### Get Your Agent Secret
Go to [dashboard.locusgraph.com](https://dashboard.locusgraph.com) and sign in.
Navigate to **Agents** and either create a new agent or select an existing one.
Click **Reveal Secret** and copy the value. You will only see it once.
Never commit agent secrets to source control. Use environment variables or a secrets manager. Rotate secrets immediately if exposed.
### Environment Variables
Set these two variables in your environment:
| Variable | Required | Default |
| ------------------------- | ------------------------------------------ | ---------------------------- |
| `LOCUSGRAPH_AGENT_SECRET` | required | — |
| `LOCUSGRAPH_SERVER_URL` | optional | `https://api.locusgraph.com` |
```bash
export LOCUSGRAPH_AGENT_SECRET="your-agent-secret"
export LOCUSGRAPH_SERVER_URL="https://api.locusgraph.com"
```
```powershell
$env:LOCUSGRAPH_AGENT_SECRET = "your-agent-secret"
$env:LOCUSGRAPH_SERVER_URL = "https://api.locusgraph.com"
```
```bash
LOCUSGRAPH_AGENT_SECRET=your-agent-secret
LOCUSGRAPH_SERVER_URL=https://api.locusgraph.com
```
### Bearer Token Format
All API requests use the `Authorization` header:
```
Authorization: Bearer
```
The SDKs handle this automatically when you pass the secret during client initialization. For raw HTTP calls, include the header manually:
```bash
curl -H "Authorization: Bearer $LOCUSGRAPH_AGENT_SECRET" \
https://api.locusgraph.com/v1/memories
```
### Next
## Introduction
LocusGraph is the wisdom graph for AI agents. It doesn't just store what agents learn — it builds structured knowledge that compounds over time.
Agents forget. Every session starts from zero. Every insight gets rediscovered. Every mistake gets repeated. LocusGraph fixes this.
### What it does
LocusGraph gives your agent five core operations:
* **Store** — Save facts, actions, decisions, observations, and feedback as structured knowledge
* **Retrieve** — Semantic search across stored wisdom with context filtering
* **Connect** — Link knowledge with `reinforces`, `contradicts`, `extends`, and `related_to`
* **Organize** — Scope knowledge by context IDs, context types, and graphs
* **Reason** — Generate insights by reasoning over accumulated wisdom
Every piece of knowledge has a source (`agent`, `user`, `system`, `validator`, `executor`), a confidence score, and typed links to other knowledge. This isn't a vector database. It's a wisdom graph.
### How agents use it
An agent with LocusGraph remembers across sessions. It tracks which patterns work, which mistakes to avoid, and what the user prefers.
The graduation chain captures this:
```
mistake → pattern → skill
```
Same error three times? It becomes a `mistake`. Same workflow across sessions? It becomes a `pattern`. Pattern used five times successfully? It becomes a `skill`. The agent grows wiser — permanently.
### Integration options
Pick the path that fits your stack:
| Method | Best for |
| ------------------ | -------------------------------------------------- |
| **MCP Server** | Claude, Cursor, Amp, and any MCP-compatible client |
| **TypeScript SDK** | Node.js agents and LangChain apps |
| **Python SDK** | Python agents and LangChain apps |
| **Rust SDK** | Performance-critical and embedded agents |
All paths give you the same five operations. The MCP server is the fastest way to start — no code required, just connect your client.
### Core concepts
Before you start building, understand these four ideas:
**Events** are the atomic unit. Every memory enters LocusGraph as an event — a `fact`, `action`, `decision`, `observation`, or `feedback`. Each event has a payload, a source, and optional links.
**Contexts** organize events. A context ID like `skill:react_best_practices` or `session:20250319_1400_ab3f` groups related memories. You filter retrieval by context to get relevant results.
**Links** create structure. `extends` builds parent-child trees. `reinforces` adds confidence. `contradicts` overrides old information. `related_to` connects across branches.
**Graphs** isolate workspaces. Each graph is a separate memory space — use one per project, per team, or per agent.
### Next steps
import { LinkCard } from '../../components/link-card.tsx'
## Quickstart
Get LocusGraph running in under five minutes: install, store knowledge, retrieve it.
import { Steps, Step } from '../../components/step.tsx'
import { CodeGroup } from '../../components/code-group.tsx'
import { Callout } from '../../components/Callout.tsx'
import { LinkCard } from '../../components/link-card.tsx'
### Prerequisites
You need an agent secret from the [LocusGraph dashboard](https://dashboard.locusgraph.com). See [Authentication](/getting-started/authentication) if you don't have one yet.
### Install
```bash
npm install @locusgraph/client
```
```bash
pip install locusgraph-client
```
```bash
cargo add locusgraph-client
```
```typescript
import { LocusGraphClient } from '@locusgraph/client';
const client = new LocusGraphClient({
agentSecret: process.env.LOCUSGRAPH_AGENT_SECRET,
graphId: 'default',
});
```
```python
from locusgraph_client import LocusGraphClient
client = LocusGraphClient(agent_secret="your-agent-secret")
```
Send an event to the wisdom graph. The admission pipeline processes it into a locus automatically.
```typescript
await client.storeEvent({
graph_id: 'default',
event_kind: 'fact',
source: 'agent',
payload: { topic: 'user_preference', value: 'dark mode' },
});
```
```python
client.store_event({
"graph_id": "default",
"event_kind": "fact",
"source": "agent",
"payload": {"topic": "user_preference", "value": "dark mode"},
})
```
Query the graph to pull back relevant knowledge.
```typescript
const result = await client.retrieveMemories({
query: 'user preferences',
limit: 5,
});
console.log(result);
```
```python
context = client.retrieve_memories(
query="user preferences",
graph_id="default",
limit=5,
)
print(context)
```
Start with the `fact` event kind for simple key-value knowledge. Explore other event kinds like `action`, `decision`, and `observation` as your agent grows.
### Next
## Managing Context Windows
Agent context windows are finite. Every token counts. Smart retrieval keeps your agent sharp.
import { Callout } from '../../components/Callout.tsx'
import { LinkCard } from '../../components/link-card.tsx'
### The Problem
Large language models have fixed context windows. Fill them with irrelevant knowledge and the agent loses focus. Fill them with too little and the agent lacks the wisdom it needs. Context engineering balances these forces.
### Retrieve Only What Matters
The first rule: do not dump the entire graph into the prompt. Use specific queries and filters to pull only the knowledge relevant to the current task.
```json
{
"tool": "retrieve_memories",
"arguments": {
"query": "payment validation edge cases",
"context_types": { "error": ["payment_validation"] },
"limit": 5
}
}
```
Five highly relevant facts beat fifty loosely related ones.
### The Graduation Chain
LocusGraph's admission pipeline naturally compresses knowledge through graduation:
1. **Mistake** — an error event records what went wrong
2. **Pattern** — repeated errors get reinforced, boosting confidence
3. **Skill** — the agent stores the learned fix as a skill event
Each step is denser and more actionable than the last. When your agent retrieves a `skill:` context, it gets the distilled wisdom without needing the full history of mistakes that led there.
Design your agent to graduate knowledge. When it solves the same problem three times, store a skill event that summarizes the solution. Link it to the original errors with `extends`.
### Summarization
For long-running agents, summarize periodically. Store a summary event that captures the key points from a session or project phase, then link it to the originals with `extends`.
```json
{
"tool": "store_event",
"arguments": {
"context_id": "session:2025_03_19_summary",
"event_kind": "observation",
"source": "agent",
"payload": {
"topic": "session summary",
"value": "Fixed 3 payment bugs. Root cause was missing null checks in middleware. Added validation layer."
},
"extends": ["session:2025_03_19"]
}
}
```
Future retrievals pull the summary instead of replaying the entire session.
### Pruning Stale Knowledge
You do not need to manually delete old knowledge. The wisdom graph handles this through confidence scoring:
* **Contradicted loci** lose confidence and drop in retrieval ranking
* **Unreinforced loci** stay at baseline confidence and get outranked by reinforced knowledge
* **Reinforced loci** rise to the top naturally
The graph acts as a living filter. Relevant, validated knowledge surfaces. Stale or incorrect knowledge fades.
### Guidelines
| Strategy | When to Use |
| ----------------------------- | ----------------------------------------------- |
| Tight scoping + low limit | Focused tasks with clear context needs |
| Broad query + moderate limit | Exploration and discovery phases |
| Summarization | End of sessions or project milestones |
| Graduation (mistake to skill) | Recurring patterns the agent should internalize |
### Next
## Designing Memory Schemas
A good schema makes knowledge discoverable. A bad one buries it.
import { Callout } from '../../components/Callout.tsx'
import { LinkCard } from '../../components/link-card.tsx'
### Context ID Conventions
Context IDs follow the format `type:name`. The type groups related knowledge; the name identifies the specific context. Use consistent prefixes across your agent.
Common type prefixes:
| Prefix | Purpose | Example |
| ---------- | -------------------------- | ----------------------- |
| `skill:` | Learned capabilities | `skill:react_hooks` |
| `error:` | Error patterns and fixes | `error:null_pointer` |
| `session:` | Session-specific context | `session:2025_03_19` |
| `project:` | Project-level knowledge | `project:auth_module` |
| `user:` | User preferences and facts | `user:display_settings` |
Pick a naming convention and stick with it. Snake case works well. Avoid spaces or special characters in names.
### Payload Design
Payloads carry the actual knowledge. The simplest pattern uses `topic` and `value` fields:
```json
{
"topic": "useEffect cleanup",
"value": "Always return a cleanup function when subscribing to external stores"
}
```
For richer knowledge, use structured objects:
```json
{
"error_type": "NullPointerException",
"trigger": "Accessing user.profile before auth check",
"fix": "Add null guard in middleware",
"confidence": "high"
}
```
Keep payloads consistent within a context type. If `error:` contexts always have `error_type`, `trigger`, and `fix` fields, retrieval results become predictable and parseable.
### Schema for a Coding Agent
Here is an example schema for an agent that assists with software development:
* **`error:null_pointer`** — stores null reference patterns, triggers, and fixes
* **`skill:react_hooks`** — stores best practices, anti-patterns, and learned techniques
* **`session:2025_03_19`** — stores decisions and observations from today's session
* **`project:auth_module`** — stores architectural decisions and module-level context
Each context type uses a consistent payload shape. The agent stores events as they occur and retrieves them by type or semantic query.
### Hierarchies and Links
Use link arrays (`reinforces`, `extends`, `contradicts`, `related_to`) to connect knowledge across contexts. When an agent encounters the same error twice, the second event `reinforces` the first. When a skill evolves, the new event `extends` the original.
Links create a connected graph instead of isolated facts. Connected knowledge ranks higher in retrieval and gives agents richer context.
### Next
## Context Engineering
Context engineering is the discipline of designing what goes into your agent's wisdom graph — and what comes back out.
import { Callout } from '../../components/Callout.tsx'
import { LinkCard } from '../../components/link-card.tsx'
### Why It Matters
The difference between an agent that flounders and one that grows wiser is not the model. It is the context. A well-engineered context strategy means your agent retrieves the right knowledge at the right time, avoids repeating mistakes, and builds on past successes.
Context engineering answers three questions:
1. **What do you store?** Not everything deserves a place in the graph. Store decisions, learned skills, error patterns, and key facts. Skip transient data.
2. **How do you structure it?** Context IDs, payload schemas, and linking strategies determine how knowledge connects and compounds.
3. **When do you retrieve it?** Query design, scoping filters, and limit tuning control what the agent sees in its context window.
### Three Pillars
#### Schema Design
Define consistent context ID conventions and payload structures. A coding agent might use `skill:react_hooks`, `error:null_pointer`, and `session:2025_03_19`. Consistency makes retrieval predictable.
#### Scoping Strategy
Use graph-level, type-level, and name-level filters to control the search space. Scoping prevents irrelevant knowledge from polluting the agent's context window.
#### Retrieval Tuning
Adjust query specificity, result limits, and context filters to balance precision and recall. Start narrow, widen only when needed.
Context engineering is iterative. Start with simple schemas, observe what your agent retrieves, and refine. The wisdom graph's confidence scoring helps surface what works and suppress what does not.
### Next
## Relevance and Retrieval
Semantic search, confidence scoring, and filters work together to surface the right knowledge.
import { Callout } from '../../components/Callout.tsx'
import { LinkCard } from '../../components/link-card.tsx'
### Semantic Search
When you call `retrieve_memories`, your query is embedded into a vector and matched against stored knowledge using semantic similarity. The graph returns results ranked by relevance — not keyword matching, but meaning.
This means a query like "handling null values" can match knowledge stored as "NullPointerException in user profile access" even though they share few exact words.
### Limit Parameter
The `limit` parameter controls how many results come back. Defaults vary, but you should set it explicitly.
* **Start small (5-10).** Most agents need a handful of relevant facts, not a wall of text.
* **Increase when exploring.** If you are surveying a broad topic, raise the limit to 20-30.
* **Decrease for precision tasks.** When the agent needs one specific answer, set limit to 3-5.
```json
{
"tool": "retrieve_memories",
"arguments": {
"query": "database connection pooling",
"limit": 5
}
}
```
### Context Filters
Filters narrow the search space before semantic matching runs. This improves both speed and relevance. See [Scoping Strategies](/context-engineering/scoping-strategies) for details on combining filters.
The order of operations:
1. Filters remove non-matching contexts from the candidate set
2. Semantic search ranks the remaining candidates
3. Confidence scoring adjusts the final ranking
4. Top results up to `limit` are returned
### Confidence and Ranking
Every locus in the wisdom graph carries a confidence score. Confidence changes over time:
* **Reinforced knowledge ranks higher.** When multiple events confirm the same fact, its confidence increases. The graph surfaces well-established wisdom first.
* **Contradicted knowledge drops.** When new evidence contradicts existing knowledge, the original locus loses confidence and falls in ranking. It does not disappear — it simply becomes less prominent.
* **Fresh knowledge starts neutral.** New loci begin with a baseline confidence. Repeated reinforcement or contradiction adjusts them over time.
You do not manage confidence manually. The wisdom graph updates confidence automatically based on event links (`reinforces`, `contradicts`). Design your agent to emit these links and the graph handles the rest.
### Retrieval Tuning Tips
1. **Be specific in queries.** "React useEffect cleanup patterns" retrieves better results than "React stuff."
2. **Combine semantic queries with type filters.** Search for "common mistakes" within `error:` contexts.
3. **Watch for noise.** If irrelevant results appear, tighten your scope or lower the limit.
4. **Use `include_ids` for debugging.** When results seem off, include locus IDs to inspect what is being returned.
### Next
## Context Scoping Strategies
Scoping controls what knowledge your agent sees. Tighter scoping means more relevant results.
import { Callout } from '../../components/Callout.tsx'
import { LinkCard } from '../../components/link-card.tsx'
### Three Levels of Scoping
#### Graph-Level Scoping
Separate graphs isolate knowledge entirely. Use different graph IDs for different projects, teams, or environments. Knowledge in one graph never leaks into another.
```json
{
"tool": "retrieve_memories",
"arguments": {
"query": "authentication patterns",
"graph_id": "project-alpha"
}
}
```
Graph-level scoping is the coarsest filter. Use it when knowledge domains are completely independent.
#### Type-Level Scoping
Filter by `context_types` to retrieve only specific categories of knowledge. This narrows the search space before semantic matching begins.
```json
{
"tool": "retrieve_memories",
"arguments": {
"query": "common mistakes",
"context_types": { "error": [] }
}
}
```
Pass an empty array to match all names within that type. Pass specific names to narrow further.
#### Name-Level Scoping
Filter by exact `context_ids` to retrieve knowledge from specific contexts only.
```json
{
"tool": "retrieve_memories",
"arguments": {
"query": "best practices",
"context_ids": ["skill:react_hooks", "skill:typescript_generics"]
}
}
```
Name-level scoping is the most precise. Use it when you know exactly which contexts are relevant.
### Combining Filters
Filters stack. Combine type-level and name-level scoping for precise retrieval.
**Example:** Retrieve only error patterns from the current project.
```json
{
"tool": "retrieve_memories",
"arguments": {
"query": "recurring bugs in payment flow",
"context_types": { "error": ["payment_null", "payment_timeout"] }
}
}
```
Start broad and narrow down. If your agent retrieves too much noise, add a type filter. If results are still noisy, scope to specific context names.
### Scoping Strategy by Use Case
| Use Case | Scope |
| --------------------------- | ------------------------------------ |
| General agent knowledge | No filters (graph-wide search) |
| Task-specific wisdom | Type filter (`skill:`, `error:`) |
| Session continuity | Name filter (`session:2025_03_19`) |
| Cross-project patterns | Graph-level separation + type filter |
| Debugging a specific module | Name filter (`error:auth_module`) |
### Next
## Contexts & Graphs
Context IDs and graph IDs scope knowledge within the wisdom graph, keeping related information grouped and isolated where needed.
import { Callout } from '../../components/Callout.tsx'
import { LinkCard } from '../../components/link-card.tsx'
### Graph IDs
A graph is a top-level workspace. Each graph is fully isolated — knowledge in one graph cannot be retrieved from another.
Use separate graphs for:
* Different projects
* Different teams
* Different agents
* Production vs. staging environments
Pass `graph_id` when initializing the client or on each API call. The default value is `"default"`.
### Context IDs
Context IDs group related knowledge within a graph. They follow a `type:name` format:
```
skill:react_best_practices
session:20250319_ab3f
project:locusgraph_docs
task:onboarding_flow
```
The type prefix (before the colon) lets you query all contexts of a given type. For example, retrieve all `skill:` contexts to see everything the agent has learned across skills.
### Format Rules
Context IDs are normalized automatically: lowercased, spaces replaced with underscores, truncated to 256 characters.
| Rule | Detail |
| ---------------- | --------------------------- |
| Format | `type:name` |
| Valid characters | `a-z`, `0-9`, `_`, `-`, `:` |
| Max length | 256 characters |
| Case | Lowercased on admission |
| Spaces | Converted to `_` |
These are all valid:
```
skill:error_handling
session:2025-03-19_morning
project:my-api
user:preferences
```
These are invalid:
```
skill:React Best Practices → normalized to skill:react_best_practices
MY_SKILL:Testing → normalized to my_skill:testing
```
### Context Types
The type prefix serves as a namespace. Common types:
| Type | Use Case |
| --------- | --------------------------------------- |
| `skill` | Learned capabilities and best practices |
| `session` | Conversation or interaction boundaries |
| `project` | Project-scoped knowledge |
| `task` | Task-specific context |
| `user` | Per-user preferences and history |
You can create any type — these are conventions, not enforced categories.
### Scoping in Practice
When storing an event, pass `context_id` to attach it to a context:
```json
{
"event_kind": "fact",
"source": "agent",
"context_id": "skill:react_best_practices",
"payload": { "topic": "hooks", "value": "prefer useReducer for complex state" }
}
```
When retrieving, filter by context to narrow results:
```json
{
"query": "state management",
"context_id": "skill:react_best_practices",
"limit": 10
}
```
### Next
## Event Kinds
Event kinds tell LocusGraph what type of knowledge you are storing, which determines how the wisdom graph processes and connects it.
import { Callout } from '../../components/Callout.tsx'
import { LinkCard } from '../../components/link-card.tsx'
### Primary Kinds
#### fact
**Aliases:** `knowledge`, `learned`
Persistent information that remains true over time. Use for preferences, configurations, and learned truths.
> "The user prefers dark mode." / "The API rate limit is 1000 req/min."
#### action
**Aliases:** `task`, `operation`, `execution`, `completed`
Something happened. A task was performed or a process completed.
> "Deployed version 2.3." / "Sent the weekly report."
#### decision
**Aliases:** `choice`, `selection`, `determination`
A choice was made with reasoning. Records the what and the why.
> "Selected PostgreSQL over MySQL for JSONB support."
#### observation
General notes and impressions. The default kind for unclassified events.
> "Build times increased after adding the new dependency."
#### feedback
Opinions, ratings, or suggestions from users. Carries subjective weight.
> "User rated the response 4/5." / "User suggested shorter summaries."
### Special Kinds
#### constraint / rule / constraint\_violation
Validation-related events. When a `constraint_violation` is stored, a `derived_from` link is auto-created to the source context.
#### routine / heartbeat / status
Mapped to `routine_operation`. Filtered from standard retrieval. Use for health checks and lifecycle tracking.
#### noise / debug / log
Mapped to `noise`. Filtered from retrieval entirely. Exists for audit only.
### Kind-to-Internal Mapping
| Input Kind | Internal Type | Retrievable |
| ------------------------------------------------------- | -------------------- | ----------- |
| `fact`, `knowledge`, `learned` | `knowledge_recorded` | Yes |
| `action`, `task`, `operation`, `execution`, `completed` | `action_completed` | Yes |
| `decision`, `choice`, `selection`, `determination` | `decision_made` | Yes |
| `observation` | `knowledge_recorded` | Yes |
| `feedback` | `knowledge_recorded` | Yes |
| `constraint`, `rule`, `constraint_violation` | `knowledge_recorded` | Yes |
| `routine`, `heartbeat`, `status` | `routine_operation` | No |
| `noise`, `debug`, `log` | `noise` | No |
When in doubt, use `fact` for things that are true and `observation` for things you noticed. The admission pipeline handles the rest.
### Next
## Memories & Events
Events are the atomic unit of knowledge in LocusGraph — every piece of wisdom enters the graph as an event.
import { Callout } from '../../components/Callout.tsx'
import { LinkCard } from '../../components/link-card.tsx'
### Events
An event represents a single piece of information submitted to the wisdom graph. Each event contains:
| Field | Required | Description |
| ------------ | -------- | ------------------------------------------------------------------------------ |
| `event_kind` | Yes | The type of knowledge: `fact`, `action`, `decision`, `observation`, `feedback` |
| `source` | Yes | Who created it: `agent`, `user`, `system`, `validator`, `executor` |
| `payload` | Yes | JSON object containing the knowledge data |
| `context_id` | No | Scope the event to a context (e.g., `skill:react_best_practices`) |
| `links` | No | Connections to other loci or contexts |
### From Event to Locus
Events do not live in the graph directly. They pass through the **admission pipeline**, which:
1. Validates the event structure and payload size.
2. Classifies the event kind into an internal type.
3. Extracts topics and relationships.
4. Creates a **locus** — a permanent node in the wisdom graph.
A locus is the graph-native representation of admitted knowledge. Once created, it participates in retrieval, linking, and confidence scoring.
### Kind Mapping
Raw event kinds map to internal types during admission:
| Input Kind | Internal Type |
| ---------------------------------- | ------------------------------ |
| `fact`, `knowledge`, `observation` | `knowledge_recorded` |
| `action`, `task` | `action_completed` |
| `decision`, `choice` | `decision_made` |
| `routine`, `heartbeat`, `status` | `routine_operation` (filtered) |
| `noise`, `debug`, `log` | `noise` (filtered) |
Events classified as `routine_operation` or `noise` are recorded but excluded from standard retrieval. They exist for audit purposes only.
### Retrieval
When you call `retrieveMemories`, LocusGraph searches across admitted loci — not raw events. The query is matched against topics, payload content, and graph connections to return the most relevant knowledge.
### Next
## Memory Links
Links connect loci in the wisdom graph, forming typed relationships that shape how knowledge is retrieved and weighted.
import { Callout } from '../../components/Callout.tsx'
import { LinkCard } from '../../components/link-card.tsx'
### Link Types
Five link types, ordered from weakest to strongest effect:
#### related\_to
General association between two loci. No side effects on confidence scoring. Use when knowledge is connected but does not modify the target.
#### extends
Adds detail to another locus. No side effects on confidence. The extending locus is returned alongside the target during retrieval.
#### derived\_from
Indicates the source locus was created because of the target. Auto-created for `constraint`, `rule`, and `constraint_violation` events when a `context_id` is present.
#### reinforces
Confirms another locus. Each `reinforces` link increases the target's confidence by **+0.05**, capped at **1.0**. Use when new evidence supports existing knowledge.
#### contradicts
Conflicts with another locus. Each `contradicts` link decreases the target's confidence by **-0.10**, with a floor of **0.2**. The target is never fully removed — low-confidence loci are deprioritized in retrieval instead.
Confidence adjustments from `reinforces` and `contradicts` are applied during admission. They compound: three `reinforces` links add +0.15 to the target's confidence.
### Link Layers
Links operate across three layers:
| Layer | Connects | Example |
| ----------------- | ------------------------------ | ------------------------------------------------ |
| Locus → Locus | Two individual knowledge nodes | A decision reinforces a fact |
| Locus → Context | A node to a context scope | A skill locus extends a session context |
| Context → Context | Two context scopes | A project context is related\_to a skill context |
### Example: Graduation Chain
Links enable knowledge to evolve. Here is how a mistake graduates into a skill:
1. **Mistake recorded.** The agent stores an observation: "Used `var` instead of `const` in React component."
2. **Pattern detected.** After seeing this twice, the agent stores a fact: "Repeated use of `var` in React." It links this to the original observation with `derived_from`.
3. **Skill formed.** The agent stores a decision: "Always use `const` or `let` in React components." It links this to the pattern with `extends` and to the original mistake with `reinforces` — confirming the learned lesson.
```
observation: "used var"
← derived_from ← fact: "repeated var pattern"
← extends ← decision: "always use const/let"
→ reinforces → observation: "used var"
```
The wisdom graph now returns the skill-level decision in retrieval, backed by the full chain of evidence.
### Creating Links
Pass links when storing an event:
```json
{
"event_kind": "fact",
"source": "agent",
"payload": { "topic": "const_usage", "value": "always use const in React" },
"links": [
{ "type": "reinforces", "target": "locus_abc123" },
{ "type": "derived_from", "target": "locus_def456" }
]
}
```
### Next
## Payload Structure
Payloads carry the actual knowledge data in an event, passed as a JSON object in the `payload` field.
import { Callout } from '../../components/Callout.tsx'
import { LinkCard } from '../../components/link-card.tsx'
### Recommended Format
Use a flat object with `topic` and `value` keys:
```json
{
"payload": {
"topic": "user_preference",
"value": "dark mode"
}
}
```
The `topic` field helps the wisdom graph index and cluster related knowledge. The `value` field holds the actual content.
### Good Payloads
Keep payloads flat and descriptive:
```json
{ "topic": "api_rate_limit", "value": "1000 requests per minute" }
```
```json
{ "topic": "deployment", "value": "v2.3 deployed to production", "environment": "prod" }
```
```json
{ "topic": "user_feedback", "value": "prefers shorter responses", "rating": 4 }
```
Adding extra flat keys alongside `topic` and `value` is fine. The admission pipeline indexes `topic` and `value` first, then scans additional keys.
### Bad Payloads
Avoid deep nesting. The admission pipeline flattens nested objects, which can lose structure:
```json
{
"user": {
"preferences": {
"theme": {
"mode": "dark",
"accent": "blue"
}
}
}
}
```
Instead, store each piece as a separate event or flatten the structure:
```json
{
"topic": "theme_mode", "value": "dark" }
}
```
```json
{
"topic": "theme_accent", "value": "blue" }
}
```
### Constraints
| Rule | Limit |
| ---------------- | ---------------------- |
| Max payload size | 256 KB |
| Max key depth | 3 levels (recommended) |
| Encoding | UTF-8 JSON |
Payloads exceeding 256 KB are rejected at the admission stage. Split large data across multiple events instead.
### Next
## Sources
Sources identify who created an event, which affects how the wisdom graph weighs and connects the resulting knowledge.
import { Callout } from '../../components/Callout.tsx'
import { LinkCard } from '../../components/link-card.tsx'
### Source Types
#### agent
The AI agent itself produced this knowledge — a decision it made, a fact it learned, or an observation during processing. Most events use this source.
```json
{ "source": "agent", "event_kind": "decision", "payload": { "topic": "database_choice", "value": "PostgreSQL" } }
```
#### user
Input from a human. Feedback, corrections, preferences, or direct instructions. User-sourced knowledge carries high trust weight in retrieval.
```json
{ "source": "user", "event_kind": "feedback", "payload": { "topic": "response_quality", "value": "too verbose" } }
```
#### system
System-level events: lifecycle signals, configuration changes, health checks. Typically paired with `routine` or `observation` event kinds.
```json
{ "source": "system", "event_kind": "routine", "payload": { "topic": "health_check", "value": "all services healthy" } }
```
#### validator
A runtime validator detected something — a constraint violation, a rule trigger, or a validation result. Events from validators often auto-create `derived_from` links.
```json
{ "source": "validator", "event_kind": "constraint_violation", "payload": { "topic": "rate_limit", "value": "exceeded 1000 req/min" } }
```
#### executor
A task executor completed work. Use when a background job, pipeline step, or automated process finishes.
```json
{ "source": "executor", "event_kind": "action", "payload": { "topic": "deployment", "value": "v2.3 deployed to production" } }
```
### How Sources Affect the Graph
Sources influence two things:
1. **Retrieval weight.** User-sourced knowledge ranks higher by default. Agent and executor sources rank equally. System and validator sources rank lower unless specifically queried.
2. **Link inference.** The admission pipeline considers the source when auto-creating links. Validator events generate `derived_from` links. Agent decisions generate `related_to` links to recent context.
You can override default source weighting in retrieval by passing explicit filters. See the retrieval API for details.
### Next
import { ApiEndpoint } from '../../components/api-endpoint.tsx'
import { ParamTable, Param } from '../../components/param-table.tsx'
import { ResponsePreview } from '../../components/response-preview.tsx'
import { Callout } from '../../components/Callout.tsx'
import { LinkCard } from '../../components/link-card.tsx'
## Generate Insights
Reason over stored knowledge in your wisdom graph to surface patterns and recommendations.
### Authentication
All requests require an `Authorization: Bearer ` header.
### Request Body
The question or task to reason about.
Graph to reason over.
Search query for relevant knowledge. Defaults to the `task` value.
Max memories to consider. Default `5`.
Filter by specific context IDs.
Filter by context types. A map of type to name arrays.
When `locus_query` is omitted, the API uses your `task` as the search query. Set `locus_query` separately when your task description is broad but you want to search a specific area of knowledge.
### Response
{`{
"insight": "Users consistently prefer dark mode interfaces. Three separate feedback events confirm this.",
"recommendation": "Set dark mode as the default theme",
"confidence": "high"
}`}
* **insight** — A synthesized finding drawn from relevant knowledge.
* **recommendation** — An actionable suggestion based on the insight.
* **confidence** — `"high"`, `"medium"`, or `"low"`.
### Examples
#### curl
```bash
curl -X POST https://api.locusgraph.com/v1/memories/insights \
-H "Authorization: Bearer " \
-H "Content-Type: application/json" \
-d '{
"task": "What UI preferences have users expressed?",
"graph_id": "graph_01",
"limit": 10,
"context_types": {
"feedback": ["ui", "design"]
}
}'
```
#### TypeScript
```typescript
import { LocusGraph } from "@locusgraph/sdk";
const locus = new LocusGraph({ agentSecret: process.env.LOCUS_SECRET });
const result = await locus.generateInsights({
task: "What UI preferences have users expressed?",
graphId: "graph_01",
limit: 10,
contextTypes: { feedback: ["ui", "design"] },
});
console.log(result.insight);
console.log(result.recommendation);
console.log(result.confidence); // "high"
```
#### Python
```python
from locusgraph import LocusGraph
locus = LocusGraph(agent_secret=os.environ["LOCUS_SECRET"])
result = locus.generate_insights(
task="What UI preferences have users expressed?",
graph_id="graph_01",
limit=10,
context_types={"feedback": ["ui", "design"]},
)
print(result.insight)
print(result.recommendation)
print(result.confidence) # "high"
```
#### Practical Pattern: Identify Recurring Issues
Use insights to detect patterns across error events:
```bash
curl -X POST https://api.locusgraph.com/v1/memories/insights \
-H "Authorization: Bearer " \
-H "Content-Type: application/json" \
-d '{
"task": "What are the most common failure patterns in the last week?",
"graph_id": "graph_01",
"locus_query": "error failure crash timeout",
"limit": 20,
"context_types": {
"error": []
}
}'
```
### Related
import { ApiEndpoint } from '../../components/api-endpoint.tsx'
import { ParamTable, Param } from '../../components/param-table.tsx'
import { ResponsePreview } from '../../components/response-preview.tsx'
import { Callout } from '../../components/Callout.tsx'
import { LinkCard } from '../../components/link-card.tsx'
## Get Context
Retrieve a single context from your wisdom graph.
### Authentication
All requests require an `Authorization: Bearer ` header.
### Query Parameters
Context ID in `"type:name"` format.
### Alternative Endpoints
#### Get by Name
#### Batch Get
Batch request body:
```json
{
"context_ids": ["skill:react_hooks", "skill:rust_lifetimes"]
}
```
### Response
{`{
"context_id": "skill:react_hooks",
"context": {
"context_type": "skill",
"context_name": "react_hooks"
},
"locus_id": "locus_abc123",
"payload": {
"topic": "react_hooks",
"value": "Use useCallback for memoized callbacks"
}
}`}
Returns `404` when the requested context does not exist.
### Examples
#### curl — Get by ID
```bash
curl -G "https://api.locusgraph.com/v1/context/graph_01" \
-H "Authorization: Bearer " \
--data-urlencode "context_id=skill:react_hooks"
```
#### curl — Get by Name
```bash
curl -G "https://api.locusgraph.com/v1/context/graph_01" \
-H "Authorization: Bearer " \
--data-urlencode "context_name=react_hooks"
```
#### curl — Batch Get
```bash
curl -X POST "https://api.locusgraph.com/v1/context/graph_01/batch" \
-H "Authorization: Bearer " \
-H "Content-Type: application/json" \
-d '{
"context_ids": ["skill:react_hooks", "skill:rust_lifetimes"]
}'
```
### Related
import { ApiEndpoint } from '../../components/api-endpoint.tsx'
import { ParamTable, Param } from '../../components/param-table.tsx'
import { ResponsePreview } from '../../components/response-preview.tsx'
import { LinkCard } from '../../components/link-card.tsx'
## List Contexts
Browse and search contexts stored in your wisdom graph.
### List Context Types
{`{
"context_types": [
{ "context_type": "skill", "count": 42 },
{ "context_type": "error", "count": 15 }
],
"total": 57,
"page": 0,
"page_size": 100
}`}
### List Contexts by Type
{`{
"contexts": [
{
"context_id": "skill:react_hooks",
"context_name": "react_hooks",
"context_type": "skill"
}
],
"total": 42,
"page": 0,
"page_size": 100
}`}
### Search Contexts
Pass a `q` query parameter to search across context names and types.
### Context Relationships
Returns all reinforcement, extension, contradiction, and related-to links for a given context.
### Authentication
All requests require an `Authorization: Bearer ` header.
### Pagination
All list endpoints return paginated results with `total`, `page`, and `page_size` fields. Use `page` and `page_size` query parameters to paginate through results.
### Examples
#### curl — List Types
```bash
curl "https://api.locusgraph.com/v1/contexts/graph_01" \
-H "Authorization: Bearer "
```
#### curl — List by Type
```bash
curl "https://api.locusgraph.com/v1/contexts/graph_01/skill" \
-H "Authorization: Bearer "
```
#### curl — Search
```bash
curl -G "https://api.locusgraph.com/v1/contexts/graph_01" \
-H "Authorization: Bearer " \
--data-urlencode "q=react"
```
#### curl — Relationships
```bash
curl "https://api.locusgraph.com/v1/contexts/graph_01/skill/react_hooks/relationships" \
-H "Authorization: Bearer "
```
### Related
import { ResponsePreview } from '../../components/response-preview.tsx'
import { Callout } from '../../components/Callout.tsx'
import { LinkCard } from '../../components/link-card.tsx'
## Response Format
All LocusGraph API responses are returned as JSON.
### Endpoint Response Shapes
#### Store Event
```json
{
"event_id": "locus_abc123",
"status": "recorded",
"relevance": "high"
}
```
* **status** — `"recorded"` or `"filtered"`.
* **relevance** — `"high"`, `"medium"`, or `"low"`.
#### Retrieve Memories
```json
{
"memories": "Formatted memory text with relevant knowledge...",
"items_found": 5
}
```
* **memories** — Formatted text with matching knowledge.
* **items\_found** — Total number of matching items.
#### Generate Insights
```json
{
"insight": "Synthesized finding from your wisdom graph.",
"recommendation": "Actionable suggestion based on the insight",
"confidence": "high"
}
```
* **confidence** — `"high"`, `"medium"`, or `"low"`.
#### List Contexts
All list endpoints return paginated results:
```json
{
"context_types": [...],
"total": 57,
"page": 0,
"page_size": 100
}
```
Use `page` and `page_size` query parameters to paginate.
### Error Responses
Errors return a JSON object with an `error` field:
```json
{
"error": "Invalid graph_id parameter"
}
```
#### Error Codes
| Status | Meaning |
| ------ | --------------------------------------------------------- |
| `400` | Bad request. Invalid parameters or payload exceeds 256KB. |
| `401` | Unauthorized. Missing or invalid `agent-secret`. |
| `404` | Not found. The requested context does not exist. |
| `429` | Rate limited. Back off and retry. |
| `500` | Internal server error. |
A `429` response means you are being rate limited. Use exponential backoff before retrying.
### SDK Error Handling
Each SDK surfaces errors in an idiomatic way.
#### TypeScript
```typescript
try {
const result = await locus.storeEvent({ ... });
} catch (err) {
// Throws Error with the API error message
console.error(err.message);
}
```
#### Python
```python
try:
result = locus.store_event(...)
except RuntimeError as e:
# Raises RuntimeError with the API error message
print(str(e))
```
#### Rust
```rust
match client.store_event(params).await {
Ok(result) => println!("{}", result.event_id),
Err(e) => eprintln!("API error: {}", e),
}
```
The Rust SDK returns `Result`, letting you handle errors with standard pattern matching.
### Related
import { ApiEndpoint } from '../../components/api-endpoint.tsx'
import { ParamTable, Param } from '../../components/param-table.tsx'
import { ResponsePreview } from '../../components/response-preview.tsx'
import { Callout } from '../../components/Callout.tsx'
import { LinkCard } from '../../components/link-card.tsx'
## Retrieve Memories
Run a semantic search over stored knowledge in your wisdom graph.
### Authentication
All requests require an `Authorization: Bearer ` header.
### Request Body
Search query for semantic matching.
Graph to search.
Max results to return.
Filter by specific context IDs.
Filter by context types. A map of type to name arrays, e.g. `{"skill": ["react", "rust"]}`.
Include locus IDs in the response.
### Response
{`{
"memories": "Formatted memory text with relevant knowledge...",
"items_found": 5
}`}
* **memories** — Formatted text containing the relevant knowledge matching your query.
* **items\_found** — Number of matching items found.
### Examples
#### curl
```bash
curl -X POST https://api.locusgraph.com/v1/memories \
-H "Authorization: Bearer " \
-H "Content-Type: application/json" \
-d '{
"query": "How should I handle React state management?",
"graph_id": "graph_01",
"limit": 10,
"context_types": {
"skill": ["react", "state_management"]
}
}'
```
#### TypeScript
```typescript
import { LocusGraph } from "@locusgraph/sdk";
const locus = new LocusGraph({ agentSecret: process.env.LOCUS_SECRET });
const result = await locus.retrieveMemories({
query: "How should I handle React state management?",
graphId: "graph_01",
limit: 10,
contextTypes: { skill: ["react", "state_management"] },
});
console.log(result.memories);
console.log(result.itemsFound); // 5
```
#### Python
```python
from locusgraph import LocusGraph
locus = LocusGraph(agent_secret=os.environ["LOCUS_SECRET"])
result = locus.retrieve_memories(
query="How should I handle React state management?",
graph_id="graph_01",
limit=10,
context_types={"skill": ["react", "state_management"]},
)
print(result.memories)
print(result.items_found) # 5
```
### Related
import { ApiEndpoint } from '../../components/api-endpoint.tsx'
import { ParamTable, Param } from '../../components/param-table.tsx'
import { ResponsePreview } from '../../components/response-preview.tsx'
import { Callout } from '../../components/Callout.tsx'
import { LinkCard } from '../../components/link-card.tsx'
## Store Event
Record a knowledge event in your wisdom graph.
### Authentication
All requests require an `Authorization: Bearer ` header.
### Request Body
Target graph ID.
Event kind. One of `"fact"`, `"action"`, `"decision"`, `"observation"`, `"feedback"`.
Event source. One of `"agent"`, `"user"`, `"system"`, `"validator"`, `"executor"`.
Primary context in `"type:name"` format.
Event payload. Max 256KB.
Context IDs this event reinforces. Max 50.
Context IDs this event extends. Max 50.
Context IDs this event contradicts. Max 50.
Related context IDs. Max 50.
Unix timestamp. Defaults to current time.
The total number of link IDs across `reinforces`, `extends`, `contradicts`, and `related_to` must not exceed 100.
### Response
{`{
"event_id": "locus_abc123",
"status": "recorded",
"relevance": "high"
}`}
* **status** — `"recorded"` (event stored) or `"filtered"` (event discarded by relevance filter).
* **relevance** — `"high"`, `"medium"`, or `"low"`.
### Examples
#### curl
```bash
curl -X POST https://api.locusgraph.com/v1/events \
-H "Authorization: Bearer " \
-H "Content-Type: application/json" \
-d '{
"graph_id": "graph_01",
"event_kind": "fact",
"context_id": "skill:react_hooks",
"payload": {
"topic": "react_hooks",
"value": "useCallback prevents unnecessary re-renders by memoizing callback references"
},
"reinforces": ["skill:react_performance"]
}'
```
#### TypeScript
```typescript
import { LocusGraph } from "@locusgraph/sdk";
const locus = new LocusGraph({ agentSecret: process.env.LOCUS_SECRET });
const result = await locus.storeEvent({
graphId: "graph_01",
eventKind: "fact",
contextId: "skill:react_hooks",
payload: {
topic: "react_hooks",
value: "useCallback prevents unnecessary re-renders by memoizing callback references",
},
reinforces: ["skill:react_performance"],
});
console.log(result.eventId); // "locus_abc123"
```
#### Python
```python
from locusgraph import LocusGraph
locus = LocusGraph(agent_secret=os.environ["LOCUS_SECRET"])
result = locus.store_event(
graph_id="graph_01",
event_kind="fact",
context_id="skill:react_hooks",
payload={
"topic": "react_hooks",
"value": "useCallback prevents unnecessary re-renders by memoizing callback references",
},
reinforces=["skill:react_performance"],
)
print(result.event_id) # "locus_abc123"
```
### Related