Skip to main content

WorkspaceBackend

Trait WorkspaceBackend 

Source
pub trait WorkspaceBackend:
    Send
    + Sync
    + 'static {
    type Conversation: ConversationBackend;

    // Required methods
    fn id(&self) -> WorkspaceId;
    fn info(
        &self,
    ) -> impl Future<Output = Result<WorkspaceInfo, KitError>> + Send + '_;
    fn new_conversation(
        &self,
        request: NewConversation,
    ) -> impl Future<Output = Result<Self::Conversation, KitError>> + Send + '_;
    fn list_conversations(
        &self,
    ) -> impl Future<Output = Result<Vec<ConversationInfo>, KitError>> + Send + '_;
    fn conversation_info(
        &self,
        id: ConversationId,
    ) -> impl Future<Output = Result<ConversationInfo, KitError>> + Send + '_;
    fn get_conversation(
        &self,
        id: ConversationId,
    ) -> impl Future<Output = Result<Self::Conversation, KitError>> + Send + '_;
    fn list_tools(
        &self,
    ) -> impl Future<Output = Result<Vec<ToolInfo>, KitError>> + Send + '_;
    fn ingest_knowledge(
        &self,
        request: IngestKnowledgeRequest,
    ) -> impl Future<Output = Result<(), KitError>> + Send + '_;
    fn close(self) -> impl Future<Output = Result<(), KitError>> + Send
       where Self: Sized;
}
Expand description

Public implementation contract for one revision-bound portable workspace.

A caller Agent returns its own concrete workspace through AgentBackend::Workspace. Each workspace owns its associated Conversation; runtime composition may use an exhaustive caller enum hierarchy. A stable workspace ID does not refresh a stale runtime revision. Closing invalidates runtime descendants while preserving quiescent durable records for direct-ID reopen.

See crate::AgentBackend::new_workspace for creation and Self::new_conversation for the child lifecycle. The executable caller hierarchy implements these contracts directly without a provider, process or database.

Required Associated Types§

Source

type Conversation: ConversationBackend

Concrete conversation implementation produced by this workspace.

Required Methods§

Source

fn id(&self) -> WorkspaceId

Returns the durable portable workspace identity.

This is the durable workspace identity. A handle also carries a runtime revision binding, so a stable id does not make an old handle current.

See Self::new_conversation for the complete child lifecycle and crate::AgentBackend::new_workspace for workspace creation.

Source

fn info( &self, ) -> impl Future<Output = Result<WorkspaceInfo, KitError>> + Send + '_

Reads the current committed workspace information.

The result contains the complete committed context/defaults and revision. It does not refresh this handle after a concurrent revision change.

§Errors

Returns KitError for a closed parent/workspace, stale revision, state-read failure, inconsistent durable state, or deadline expiry.

See Self::new_conversation for the complete child lifecycle and crate::AgentBackend::new_workspace for workspace creation.

Source

fn new_conversation( &self, request: NewConversation, ) -> impl Future<Output = Result<Self::Conversation, KitError>> + Send + '_

Creates and publishes one conversation under this workspace.

The returned associated child is published only after resolved defaults, initial knowledge, backend attachment, and durable ownership agree.

§Errors

Returns KitError for closed or stale runtime, busy admission, invalid input or unsupported policy/integrations, and dependency/deadline failures. Accepted native setup remains durably attached or recovery-owned on failure.

§Examples

This local Custom agent uses in-memory Lance and sends no network requests.

#![recursion_limit = "256"] // Nested concrete async futures need this on Linux.
use agents_kit::ConversationBackend;
use agents_kit::conversation::NewConversation;
let workspace_id = workspace.id();
let result = async {
    let conversation = workspace.new_conversation(NewConversation::new(
        Some("Review".into()), None, Vec::new(),
    )?).await?;
    let id = conversation.id();
    let info = conversation.info().await?;
    assert_eq!(info.id(), &id);
    assert_eq!(info.workspace_id(), &workspace_id);
    assert_eq!(info.title(), Some("Review"));
    let inventory = workspace.list_conversations().await?;
    assert_eq!(inventory.len(), 1);
    assert_eq!(inventory[0].id(), &id);
    assert_eq!(workspace.conversation_info(id.clone()).await?.id(), &id);
    assert!(workspace.list_tools().await?.is_empty());
    Ok::<_, agents_kit::KitError>(id)
}.await;
// Parent close settles children and preserves quiescent records for reopen.
let close = workspace.close().await;
let conversation_id = match (result, close) {
    (Err(primary), Err(cleanup)) => Err(primary.with_supplementary(cleanup)),
    (Err(error), _) | (_, Err(error)) => Err(error),
    (Ok(id), Ok(())) => Ok(id),
}?;
let workspace = agent.get_workspace(workspace_id.clone()).await?;
let result = async {
    assert_eq!(workspace.id(), workspace_id);
    assert_eq!(workspace.info().await?.id(), &workspace_id);
    let conversation = workspace.get_conversation(conversation_id.clone()).await?;
    let observed = conversation.info().await;
    // Explicit child close is terminal; unlike parent close, it ends reopenability.
    let close = conversation.close().await;
    let info = match (observed, close) {
        (Err(primary), Err(cleanup)) => Err(primary.with_supplementary(cleanup)),
        (Err(error), _) | (_, Err(error)) => Err(error),
        (Ok(info), Ok(())) => Ok(info),
    }?;
    assert_eq!(info.id(), &conversation_id);
    assert_eq!(info.workspace_id(), &workspace_id);
    assert_eq!(info.title(), Some("Review"));
    assert!(workspace.list_conversations().await?.is_empty());
    Ok::<(), agents_kit::KitError>(())
}.await;
let close = workspace.close().await;
match (result, close) {
    (Err(primary), Err(cleanup)) => Err(primary.with_supplementary(cleanup)),
    (Err(error), _) | (_, Err(error)) => Err(error),
    (Ok(()), Ok(())) => Ok(()),
}?;
Source

fn list_conversations( &self, ) -> impl Future<Output = Result<Vec<ConversationInfo>, KitError>> + Send + '_

Lists live or reopenable conversations in deterministic identity order.

Inventory comes from ownership-valid durable records; it is not limited to handles currently open in this process. Terminally closed conversations are excluded. Listing does not claim live handles.

§Errors

Returns KitError for closed or stale runtime, state/dependency read failures, inconsistent inventory, or deadline expiry.

See Self::new_conversation for the complete child lifecycle and crate::AgentBackend::new_workspace for workspace creation.

Source

fn conversation_info( &self, id: ConversationId, ) -> impl Future<Output = Result<ConversationInfo, KitError>> + Send + '_

Reads committed information for one conversation identity.

This reads committed metadata without claiming a live child handle. Missing and foreign identities do not reveal a foreign owner.

§Errors

Returns crate::error::ErrorKind::NotFound for an unavailable or foreign conversation, or the owning closed/stale runtime, state-read, integrity, or deadline error.

See Self::new_conversation for the complete child lifecycle and crate::AgentBackend::new_workspace for workspace creation.

Source

fn get_conversation( &self, id: ConversationId, ) -> impl Future<Output = Result<Self::Conversation, KitError>> + Send + '_

Opens the current live handle for one conversation identity.

A current conversation has at most one live public handle; repeated lookup is busy until its claim is released. Reopen verifies the current workspace revision, defaults, attachments, tools, knowledge, and recovery state. It does not create a replacement session for a missing identity.

§Errors

Returns KitError for a missing/foreign or terminal conversation, an existing live claim, closed or stale runtime, incompatible reopen state, or dependency/deadline failure.

See Self::new_conversation for the complete child lifecycle and crate::AgentBackend::new_workspace for workspace creation.

Source

fn list_tools( &self, ) -> impl Future<Output = Result<Vec<ToolInfo>, KitError>> + Send + '_

Lists agents-kit-managed tools installed for this workspace.

Returns the complete source-neutral catalog the Agent owns and can expose in this workspace, subject to its execution policy. An unavailable source must not be silently omitted from a purportedly complete result.

§Errors

Returns KitError for closed or stale runtime, unsupported or incomplete catalog exposure, malformed source data, or dependency/deadline failure.

See Self::new_conversation for the complete child lifecycle and crate::AgentBackend::new_workspace for workspace creation.

Source

fn ingest_knowledge( &self, request: IngestKnowledgeRequest, ) -> impl Future<Output = Result<(), KitError>> + Send + '_

Atomically replaces managed knowledge from this workspace.

An omitted scope selects this Workspace. Explicit Agent or Database scope is validated under the shared knowledge rules; Conversation scope is not accepted here. Empty sources are a no-op after scope validation, not deletion. Updating workspace context/defaults does not move sources. See crate::knowledge for local ingestion and policy examples.

§Errors

Returns KitError for invalid sources or scope, missing/incompatible knowledge integrations, closed or stale runtime, busy admission, or dependency/deadline failure. Unsupported semantics fail explicitly.

Caller implementations need no service. See IngestKnowledgeRequest for request construction and the executable caller hierarchy for direct-trait ingestion.

Source

fn close(self) -> impl Future<Output = Result<(), KitError>> + Send
where Self: Sized,

Consumes the implementation, seals its runtime, and settles accepted work.

Close cascade-invalidates live descendants after accepted work and interactions settle. Quiescent durable conversations, notifications, and knowledge remain for reopen. This does not terminally close conversations or acknowledge caller events. Drop alone provides no async cleanup guarantee.

§Errors

Returns KitError when an owned cleanup responsibility fails or cannot settle within the lifecycle deadline. The consumed handle is not restored; durable recovery owns later reconciliation and supplementary failures do not replace the primary error.

See Self::new_conversation for the complete child lifecycle and crate::AgentBackend::new_workspace for workspace creation.

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§