From 1c3abf64107e2e669f05f112eacbd6810dc41c45 Mon Sep 17 00:00:00 2001 From: Cameron Pfiffer Date: Thu, 26 Mar 2026 20:37:36 -0700 Subject: [PATCH] feat: Add boot context endpoint for new agents MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implements #66: network.comind.context.load Unlike raw search, this endpoint: - Deduplicates near-identical results (agents often echo each other) - Prioritizes concepts and claims over reasoning traces - Diversifies across agents (don't return 20 results from one agent) - Returns agent metadata for context New agents can query the collective knowledge graph on their domain instead of starting from zero. Lexicon: indexer/lexicons/network.comind.context.load.json Implementation: indexer/indexer/app.py 👾 Generated with [Letta Code](https://letta.com) Co-Authored-By: Letta Code --- indexer/indexer/app.py | 80 +++++++++++++++++++ .../lexicons/network.comind.context.load.json | 67 ++++++++++++++++ 2 files changed, 147 insertions(+) create mode 100644 indexer/lexicons/network.comind.context.load.json diff --git a/indexer/indexer/app.py b/indexer/indexer/app.py index b8539f5..1c47450 100644 --- a/indexer/indexer/app.py +++ b/indexer/indexer/app.py @@ -169,6 +169,85 @@ def create_app() -> Flask: finally: session.close() + @server.method("network.comind.context.load") + def context_load(input, q=None, limit=20, diversity=True): + """Load context for a new agent starting cold. + + Unlike raw search, this endpoint: + - Deduplicates near-identical results (agents often echo each other) + - Prefers concepts and claims over raw reasoning traces + - Includes source agent metadata (handle, not just DID) + - Optionally diversifies across agents (don't return 20 results from one agent) + """ + if not q: + return {"context": [], "agents": []} + + # Generate embedding for query + query_embedding = embeddings.embed_text(q) + + session = db.get_session(engine) + try: + # Get more results than needed for dedup/diversity + raw_results = db.search_similar( + session, + query_embedding, + limit=limit * 3 if diversity else limit * 2, + ) + + # Prioritize concept/claim over reasoning traces + priority_collections = { + "network.comind.concept": 3, + "network.comind.claim": 3, + "network.comind.hypothesis": 2, + "network.comind.memory": 1, + "network.comind.thought": 1, + } + + # Score and deduplicate + seen_content = set() + seen_dids = set() + context = [] + agent_handles = {} + + for record, score in raw_results: + if len(context) >= limit: + break + + # Skip near-duplicate content (first 100 chars) + content_key = (record.content or "")[:100].lower() + if content_key in seen_content: + continue + seen_content.add(content_key) + + # Diversity: limit results per agent + if diversity and record.did in seen_dids and len(seen_dids) < 5: + continue + + # Boost priority collections + priority = priority_collections.get(record.collection, 0) + adjusted_score = score + (priority * 0.1) + + seen_dids.add(record.did) + if record.handle: + agent_handles[record.did] = record.handle + + context.append({ + "uri": record.uri, + "did": record.did, + "handle": record.handle, + "collection": record.collection, + "content": record.content[:500] if record.content else None, + "score": round(adjusted_score, 4), + "createdAt": record.created_at.isoformat() if record.created_at else None, + }) + + # Build agent list + agents = [{"did": did, "handle": handle} for did, handle in agent_handles.items()] + + return {"context": context, "agents": agents} + finally: + session.close() + # Attach XRPC server to Flask app init_flask(server, app) @@ -193,6 +272,7 @@ def create_app() -> Flask: "endpoints": [ "/xrpc/network.comind.search.query", "/xrpc/network.comind.search.similar", + "/xrpc/network.comind.context.load", "/xrpc/network.comind.agents.list", "/xrpc/network.comind.index.stats", ], diff --git a/indexer/lexicons/network.comind.context.load.json b/indexer/lexicons/network.comind.context.load.json new file mode 100644 index 0000000..f7ff333 --- /dev/null +++ b/indexer/lexicons/network.comind.context.load.json @@ -0,0 +1,67 @@ +{ + "lexicon": 1, + "id": "network.comind.context.load", + "defs": { + "main": { + "type": "query", + "description": "Load context for a new agent starting cold. Unlike raw search, this endpoint deduplicates near-identical results, prioritizes concepts and claims over reasoning traces, and diversifies across agents.", + "parameters": { + "type": "params", + "properties": { + "q": { + "type": "string", + "description": "Natural language query for the domain/topic (e.g., 'identity persistence', 'coordination patterns')", + "maxLength": 500 + }, + "limit": { + "type": "integer", + "description": "Maximum number of context records to return", + "default": 20, + "minimum": 1, + "maximum": 50 + }, + "diversity": { + "type": "boolean", + "description": "Whether to diversify results across agents (default: true)", + "default": true + } + }, + "required": ["q"] + }, + "output": { + "encoding": "application/json", + "schema": { + "type": "object", + "required": ["context", "agents"], + "properties": { + "context": { + "type": "array", + "items": { + "type": "object", + "properties": { + "uri": { "type": "string" }, + "did": { "type": "string" }, + "handle": { "type": "string" }, + "collection": { "type": "string" }, + "content": { "type": "string" }, + "score": { "type": "number" }, + "createdAt": { "type": "string" } + } + } + }, + "agents": { + "type": "array", + "items": { + "type": "object", + "properties": { + "did": { "type": "string" }, + "handle": { "type": "string" } + } + } + } + } + } + } + } + } +} -- 2.51.2