Portal Community

Collection Naming Convention

// Collection name format
string GetCollectionName(AgentComposite agent) =>
    $"agent_{agent.Id:N}_{agent.TenantId.Replace("-", "_")}";

// Example collection names:
// agent_5e7d3a1b0c8f4e2a9d6b7c5e3f1a2b4c_tenant_acmecorp
// agent_8a9f2e4c1b5d7f3e6a8c0d2b4f6e8a0c_tenant_acmecorp

// A Finance agent and HR agent in the same tenant have DIFFERENT collections:
// → Finance: agent_{financeId}_tenant_acmecorp
// → HR:      agent_{hrId}_tenant_acmecorp

Shared Knowledge Collections

In some cases, multiple agents should share a common knowledge base (e.g., company-wide policies visible to all agents). This is supported via a shared collection that agents opt into:

// Shared collection configuration
public class SharedKnowledgeConfig
{
    public bool UseSharedCollection { get; set; } = false;
    public string? SharedCollectionName { get; set; }    // tenant-scoped shared collection
    public int SharedTopK { get; set; } = 2;             // results from shared collection
    // Total results = SemanticTopK (agent-specific) + SharedTopK (shared)
}

// Retrieval with shared collection
var agentResults = await _store.SearchAsync(agentCollection, queryEmbedding, topK: 5);
var sharedResults = config.UseSharedCollection
    ? await _store.SearchAsync(sharedCollection, queryEmbedding, topK: 2)
    : Enumerable.Empty<MemoryRecord>();

var combined = agentResults.Concat(sharedResults).ToList();

Cross-Agent Access Prevention

The Octopus API enforces collection access. When an agent performs a semantic search, the collection name is derived from the agent's ID — not from any user-provided input. There is no API that allows specifying an arbitrary collection name at retrieval time:

// In SemanticMemoryService — collection is always derived from the agent, not from user input
public async Task<SemanticRetrievalResult> RetrieveAsync(
    AgentComposite agent,    // only the loaded agent can determine the collection
    string query, CancellationToken ct)
{
    // collection is derived from agent identity — cannot be overridden
    var collection = GetCollectionName(agent);  // e.g., "agent_5e7d..."

    return await _store.SearchAsync(collection, ...);
    // User input cannot change which collection is searched
}
Design Principle: Isolation by Default

The default is maximum isolation — each agent only searches its own collection. Shared access must be explicitly configured. This means a newly created agent starts with an empty knowledge base and cannot accidentally inherit knowledge from other agents.