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§
Sourcetype Workspace: WorkspaceBackend
type Workspace: WorkspaceBackend
Concrete workspace implementation produced by this agent.
Required Methods§
Sourcefn id(&self) -> AgentId
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.
Sourcefn info(&self) -> impl Future<Output = Result<AgentInfo, KitError>> + Send + '_
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.
Sourcefn new_workspace(
&self,
request: NewWorkspace,
) -> impl Future<Output = Result<Self::Workspace, KitError>> + Send + '_
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());Sourcefn list_workspaces(
&self,
) -> impl Future<Output = Result<Vec<WorkspaceInfo>, KitError>> + Send + '_
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.
Sourcefn workspace_info(
&self,
id: WorkspaceId,
) -> impl Future<Output = Result<WorkspaceInfo, KitError>> + Send + '_
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.
Sourcefn get_workspace(
&self,
id: WorkspaceId,
) -> impl Future<Output = Result<Self::Workspace, KitError>> + Send + '_
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.
Sourcefn check_workspace_update(
&self,
request: &UpdateWorkspaceRequest,
) -> impl Future<Output = Result<WorkspaceUpdateReadiness, KitError>> + Send + '_
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.
Sourcefn update_workspace(
&self,
request: UpdateWorkspaceRequest,
) -> impl Future<Output = Result<WorkspaceInfo, KitError>> + Send + '_
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.
Sourcefn delete_workspace(
&self,
request: DeleteWorkspaceRequest,
) -> impl Future<Output = Result<(), KitError>> + Send + '_
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.
Sourcefn list_models(
&self,
) -> impl Future<Output = Result<Vec<ModelInfo>, KitError>> + Send + '_
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.
Sourcefn ingest_knowledge(
&self,
request: IngestKnowledgeRequest,
) -> impl Future<Output = Result<(), KitError>> + Send + '_
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.
Sourcefn shutdown(self) -> impl Future<Output = Result<(), KitError>> + Sendwhere
Self: Sized,
fn shutdown(self) -> impl Future<Output = Result<(), KitError>> + Sendwhere
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".