Skip to main content

AgentBackend

Trait AgentBackend 

Source
pub trait AgentBackend:
    Send
    + Sync
    + 'static {
    type Workspace: WorkspaceBackend;

    // Required methods
    fn id(&self) -> AgentId;
    fn info(
        &self,
    ) -> impl Future<Output = Result<AgentInfo, KitError>> + Send + '_;
    fn new_workspace(
        &self,
        request: NewWorkspace,
    ) -> impl Future<Output = Result<Self::Workspace, KitError>> + Send + '_;
    fn list_workspaces(
        &self,
    ) -> impl Future<Output = Result<Vec<WorkspaceInfo>, KitError>> + Send + '_;
    fn workspace_info(
        &self,
        id: WorkspaceId,
    ) -> impl Future<Output = Result<WorkspaceInfo, KitError>> + Send + '_;
    fn get_workspace(
        &self,
        id: WorkspaceId,
    ) -> impl Future<Output = Result<Self::Workspace, KitError>> + Send + '_;
    fn check_workspace_update(
        &self,
        request: &UpdateWorkspaceRequest,
    ) -> impl Future<Output = Result<WorkspaceUpdateReadiness, KitError>> + Send + '_;
    fn update_workspace(
        &self,
        request: UpdateWorkspaceRequest,
    ) -> impl Future<Output = Result<WorkspaceInfo, KitError>> + Send + '_;
    fn delete_workspace(
        &self,
        request: DeleteWorkspaceRequest,
    ) -> impl Future<Output = Result<(), KitError>> + Send + '_;
    fn list_models(
        &self,
    ) -> impl Future<Output = Result<Vec<ModelInfo>, KitError>> + Send + '_;
    fn ingest_knowledge(
        &self,
        request: IngestKnowledgeRequest,
    ) -> impl Future<Output = Result<(), KitError>> + Send + '_;
    fn shutdown(self) -> impl Future<Output = Result<(), KitError>> + Send
       where Self: Sized;
}
Expand description

Public implementation contract for a complete portable agent runtime.

Built-ins and caller implementations use this behavioral boundary directly. A caller implementation returns its own concrete Workspace, whose associated Conversation remains concrete. Runtime selection may use an exhaustive caller-owned enum hierarchy; no normalization constructor or independent child type parameter is needed.

Accepted work must reach its documented durable terminal state even if a caller drops the awaiting future. Shutdown seals new work, invalidates live descendants, and settles accepted cleanup.

Start with the local construction example and Self::new_workspace. For a complete caller-owned hierarchy, the executable direct-trait examples cover Agent, associated Workspace and Conversation, exact requests, lifecycle and errors. Their process-local state is not native durability evidence. The Custom composition tests exercise the real Custom runtime with caller-owned lower implementations.

Required Associated Types§

Source

type Workspace: WorkspaceBackend

Concrete workspace implementation produced by this agent.

Required Methods§

Source

fn id(&self) -> AgentId

Returns the durable portable agent identity.

The identity remains stable across runtime reopen. This value identifies the durable Agent; it does not expose backend routing or lower resources.

See the local construction example and Self::new_workspace for child ownership.

Source

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

Loads the current descriptive agent information.

§Errors

Returns KitError if the runtime is closed, committed state cannot be read, or stored facts contradict the portable record contract.

See the local construction example and Self::new_workspace for child ownership.

Source

fn new_workspace( &self, request: NewWorkspace, ) -> impl Future<Output = Result<Self::Workspace, KitError>> + Send + '_

Creates and publishes a workspace from validated portable configuration.

Publishes a handle only after complete context/defaults, backend attachment, and durable ownership agree. A new workspace begins at revision one.

§Errors

Returns KitError for closed or busy admission, unsupported execution policy/integration composition, invalid input, dependency failure, or deadline expiry. Accepted native setup must remain durably attached or recovery-owned when an operation fails.

§Examples

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

let workspace = agent.new_workspace(
    NewWorkspace::new("review", context, WorkspaceDefaults::empty())?,
).await?;
use agents_kit::workspace::{UpdateWorkspaceRequest, WorkspaceUpdateReadiness, DeleteWorkspaceRequest};
let observed = async {
    let current = workspace.info().await?;
    assert_eq!(current.revision(), 1);
    let request = UpdateWorkspaceRequest::new(current.id().clone(), current.revision(),
        "renamed", current.context().clone(), current.defaults().clone())?;
    // Preflight observes the still-open workspace runtime.
    assert_eq!(agent.check_workspace_update(&request).await?, WorkspaceUpdateReadiness::Ready);
    // Readiness is advisory: it does not reserve or change the revision.
    assert_eq!(agent.workspace_info(current.id().clone()).await?.revision(), current.revision());
    Ok::<_, agents_kit::KitError>((current, request))
}.await;
let close = workspace.close().await;
let (current, request) = match (observed, close) {
    (Ok(value), Ok(())) => Ok(value),
    (Err(primary), Err(cleanup)) => Err(primary.with_supplementary(cleanup)),
    (Err(error), _) | (_, Err(error)) => Err(error),
}?;
// Revision-checked mutations also accept a quiescent, closed workspace.
let updated = agent.update_workspace(request).await?;
assert_eq!(updated.name(), "renamed");
assert_eq!(updated.revision(), current.revision() + 1);
agent.delete_workspace(DeleteWorkspaceRequest::new(updated.id().clone(), updated.revision())?).await?;
assert!(agent.list_workspaces().await?.is_empty());
Source

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

Lists the agent’s durable workspaces.

Inventory comes from committed records, not only currently opened handles. The result does not claim live ownership of those workspaces.

§Errors

Returns KitError for a closed runtime, state-read failure, deadline expiry, or inconsistent durable inventory.

See the local construction example and Self::new_workspace for child ownership.

Source

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

Loads descriptive information for a workspace identity.

This reads committed metadata without claiming a live workspace handle. Missing and foreign identities are both reported without revealing owners.

§Errors

Returns crate::error::ErrorKind::NotFound for a missing or foreign id, or the owning lifecycle, state-read, integrity, or deadline error.

See the local construction example and Self::new_workspace for child ownership.

Source

fn get_workspace( &self, id: WorkspaceId, ) -> impl Future<Output = Result<Self::Workspace, KitError>> + Send + '_

Reopens a durable workspace as a live handle.

At most one live handle exists for a current workspace revision. Share it by reference; a second current-revision lookup is busy. Reopen verifies durable attachment and integration compatibility rather than inventing a replacement workspace.

§Errors

Returns KitError for a missing/foreign id, an existing live claim, closed runtime, incompatible reopen state, dependency failure, or timeout.

See WorkspaceBackend::new_conversation for an inventory and reopen workflow, including release of the first workspace claim before lookup.

Source

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

Performs a read-only advisory preflight for a workspace replacement.

A completed Ready reserves no later mutation right. The durable expected revision is checked before dynamic readiness; the preflight excludes its own transient admission from the activity it reports.

§Errors

Returns KitError for invalid or unsupported replacement data, a missing/foreign workspace, stale revision, closed runtime, or an owning state/dependency/deadline failure. Dynamic activity is reported as WorkspaceUpdateReadiness::Busy.

See Self::new_workspace for a complete creation, revision-check, replacement and deletion workflow.

Source

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

Atomically applies a revision-checked portable workspace replacement.

This is a full replacement of name, context, and defaults, not a patch. The operation rechecks revision and activity atomically, preserves the backend attachment, increments the revision once, and invalidates prior workspace/conversation handles only after durable commit. Commit is success; postcommit cleanup cannot change it into an error.

§Errors

Returns KitError for stale revision, busy or ambiguous descendant work, missing/foreign identity, unsupported replacement policy, closed runtime, or precommit dependency/deadline failures. Revision overflow is crate::error::ErrorKind::InvalidState and does not change state.

See Self::new_workspace for a complete creation, revision-check, replacement and deletion workflow.

Source

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

Deletes a workspace after validating its expected revision.

Requires quiescent descendants and the current revision; there is no force mode. Durable removal of workspace/child inventory is the success boundary. Postcommit native cleanup remains a recovery obligation and cannot reverse success.

§Errors

Returns KitError for stale revision, active or ambiguous descendants, missing/foreign identity, closed runtime, or precommit state/dependency/ deadline failure.

See Self::new_workspace for a complete creation, revision-check, replacement and deletion workflow.

Source

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

Lists selectable models in stable canonical-selector order.

The complete selectable inventory retains canonical selectors and supported reasoning/personality values. Listing does not reserve future availability; selection is revalidated in the eventual workspace/conversation context.

§Errors

Returns KitError when the inventory route is unsupported or incomplete, selected external data is malformed, the runtime is closed, or a dependency operation fails or times out. An unavailable inventory is not an empty success.

Caller implementations need no service. The executable caller hierarchy exercises this contract with direct trait mocks; supplied backends retain their own prerequisites.

Source

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

Replaces the agent-scoped managed-knowledge source set.

An omitted scope selects Agent scope; an explicit Database scope follows the managed-knowledge contract. Nonempty ingestion replaces the selected source set atomically; an empty request is a no-op after scope validation, not deletion. It does not execute a prompt or create tools. See crate::knowledge for a complete local ingestion workflow.

§Errors

Returns KitError for invalid source/scope data, missing or incompatible knowledge integrations, closed or busy admission, dependency failures, or timeout. Unsupported scope or backend semantics fail explicitly.

Caller implementations need no service. The executable caller hierarchy exercises this contract with direct trait mocks; supplied backends retain their own prerequisites.

Source

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

Consumes the implementation, seals new work, and settles owned cleanup.

Live descendants are invalidated after accepted work and cleanup settle. Quiescent durable workspaces and conversations remain available to a new parent runtime. Dropping an Agent provides no asynchronous cleanup guarantee.

§Errors

Returns KitError if consuming cleanup cannot fully settle within the lifecycle deadline or an owned resource fails cleanup. The owner is not restored; preserve the primary error and its supplementary cleanup facts and use durable state for later reconciliation.

See the local construction example and Self::new_workspace for child ownership.

Dyn Compatibility§

This trait is not dyn compatible.

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

Implementors§

Source§

impl<S, D, P, T> AgentBackend for Agent<S, D, P, T>

Source§

type Workspace = Workspace<S, D, P, T>