Shared contracts for the Agentra ecosystem.
This crate defines the traits, types, and standards that ALL sisters must implement. It serves as the single source of truth for the ecosystem.
[dependencies]
agentic-sdk = "0.2"The foundation that all sisters implement:
use agentic_sdk::prelude::*;
pub struct MyNewSister { /* ... */ }
impl Sister for MyNewSister {
const SISTER_TYPE: SisterType = SisterType::Memory;
const FILE_EXTENSION: &'static str = "amem";
fn init(config: SisterConfig) -> SisterResult<Self> { /* ... */ }
fn health(&self) -> HealthStatus { /* ... */ }
fn version(&self) -> Version { /* ... */ }
fn shutdown(&mut self) -> SisterResult<()> { /* ... */ }
fn capabilities(&self) -> Vec<Capability> { /* ... */ }
}Append-only sequential sessions (Memory, Vision, Identity):
impl SessionManagement for MyNewSister {
fn start_session(&mut self, name: &str) -> SisterResult<ContextId> { /* ... */ }
fn end_session(&mut self) -> SisterResult<()> { /* ... */ }
fn current_session(&self) -> Option<ContextId> { /* ... */ }
fn export_session(&self, id: ContextId) -> SisterResult<ContextSnapshot> { /* ... */ }
fn import_session(&mut self, snapshot: ContextSnapshot) -> SisterResult<ContextId> { /* ... */ }
}Switchable named workspaces (Codebase):
impl WorkspaceManagement for MyNewSister {
fn create_workspace(&mut self, name: &str) -> SisterResult<ContextId> { /* ... */ }
fn switch_workspace(&mut self, id: ContextId) -> SisterResult<()> { /* ... */ }
fn current_workspace(&self) -> Option<ContextId> { /* ... */ }
fn delete_workspace(&mut self, id: ContextId) -> SisterResult<()> { /* ... */ }
}Search-based claim verification:
impl Grounding for MyNewSister {
fn ground(&self, claim: &str) -> SisterResult<GroundingResult> { /* ... */ }
fn evidence(&self, query: &str, max_results: usize) -> SisterResult<Vec<EvidenceDetail>> { /* ... */ }
fn suggest(&self, query: &str, limit: usize) -> SisterResult<Vec<GroundingSuggestion>> { /* ... */ }
}Standard query interface:
impl Queryable for MyNewSister {
fn query(&self, query: Query) -> SisterResult<QueryResult> { /* ... */ }
fn supports_query(&self, query_type: &str) -> bool { /* ... */ }
fn query_types(&self) -> Vec<QueryTypeInfo> { /* ... */ }
}Observability events:
impl EventEmitter for MyNewSister {
fn subscribe(&self, filter: EventFilter) -> EventReceiver { /* ... */ }
fn recent_events(&self, limit: usize) -> Vec<SisterEvent> { /* ... */ }
fn emit(&self, event: SisterEvent) { /* ... */ }
}Each sister uses its own binary header format. The contracts provide
FileFormatReader and FileFormatWriter traits for unified access:
use agentic_sdk::file_format::*;
impl FileFormatReader for MyNewSister {
fn can_read(&self, path: &Path) -> bool { /* check magic bytes */ }
fn file_info(&self, path: &Path) -> SisterResult<FileInfo> { /* ... */ }
fn file_version(&self, path: &Path) -> SisterResult<Version> { /* ... */ }
}
impl FileFormatWriter for MyNewSister {
fn write_file(&self, path: &Path) -> SisterResult<()> { /* ... */ }
fn export_bytes(&self) -> SisterResult<Vec<u8>> { /* ... */ }
}Two-layer error model across all sisters:
use agentic_sdk::errors::*;
// Domain errors (tool execution failures -> isError: true in MCP)
let err = SisterError::not_found("node_123");
let err = SisterError::invalid_input("name cannot be empty");
let err = SisterError::storage("Failed to write file");
// Protocol errors (routing failures -> JSON-RPC error response)
let err = ProtocolError::tool_not_found("unknown_tool");
let err = ProtocolError::invalid_params("missing required field 'name'");| Sister | Type | Extension | Status |
|---|---|---|---|
| Memory | SisterType::Memory |
.amem |
✅ Shipped |
| Vision | SisterType::Vision |
.avis |
✅ Shipped |
| Codebase | SisterType::Codebase |
.acb |
✅ Shipped |
| Identity | SisterType::Identity |
.aid |
✅ Shipped |
| Time | SisterType::Time |
.atime |
✅ Shipped |
MIT