pub struct KnowledgeChatRuntime { /* private fields */ }Expand description
A real, knowledge-grounded chat runtime over smooth-operator.
This is the first end-to-end “knowledge-chat turn” for smooth-operator: it
wires a StorageAdapter’s KnowledgeBase
into a smooth-operator Agent two ways —
- Auto-injected context via
AgentConfig::with_knowledge: the engine queries the KB with the user’s message and prepends the top matches as a[Relevant knowledge]system message before the first LLM call. - Agent-driven search via the
KnowledgeSearchTool: the model can issue its ownknowledge_searchquery mid-turn with its own phrasing.
Construct with KnowledgeChatRuntime::new for production (a real
LlmClient is built from the
LlmConfig), or inject a mock via
KnowledgeChatRuntime::with_llm_provider for deterministic, key-free
tests.
Implementations§
Source§impl KnowledgeChatRuntime
impl KnowledgeChatRuntime
Sourcepub fn new(storage: Arc<dyn StorageAdapter>, llm: LlmConfig) -> Self
pub fn new(storage: Arc<dyn StorageAdapter>, llm: LlmConfig) -> Self
Build a production runtime over a storage adapter and LLM config.
Sourcepub fn with_curation(
self,
store: CuratedKnowledgeStore,
context: AccessContext,
filter: RetrievalFilter,
) -> Self
pub fn with_curation( self, store: CuratedKnowledgeStore, context: AccessContext, filter: RetrievalFilter, ) -> Self
Enable query-time curation for this runtime (Phase 11): scope retrieval to named document sets / metadata equalities and re-rank by per-document boost.
store is a CuratedKnowledgeStore wrapping the same inner
KnowledgeBase the documents were
ingested through (so its curation + ACL side tables are populated),
context is the requester’s identity (ACL ∧ curation both apply — the
curated store enforces document-level access control itself), and filter
scopes the reads. Both the auto-injected [Relevant knowledge] context and
the knowledge_search tool read through this filtered, boosted reader.
Pass RetrievalFilter::none to apply boost re-ranking with no
set/metadata scoping. Without calling this, retrieval is unchanged.
Sourcepub fn with_retrieval_filter(self, filter: RetrievalFilter) -> Self
pub fn with_retrieval_filter(self, filter: RetrievalFilter) -> Self
Set (or replace) just the RetrievalFilter on an already-configured
curation store, so a per-turn scope can be applied without rebuilding the
store. No-op (logs nothing) when curation is not configured.
Sourcepub fn with_access_control(
self,
store: AclKnowledgeStore,
context: AccessContext,
) -> Self
pub fn with_access_control( self, store: AclKnowledgeStore, context: AccessContext, ) -> Self
Enable document-level access control for this runtime (feature gap G3).
store is an AclKnowledgeStore that wraps the same inner
KnowledgeBase the documents were
ingested through (so its ACL side table is populated), and context is
the requester’s identity. With this set, every turn reads knowledge
through an AccessContext-bound reader — both the auto-injected
[Relevant knowledge] context and the knowledge_search tool drop
documents the requester is not entitled to.
Without it, the runtime reads the raw storage.knowledge() exactly as
before (backward-compatible — existing no-ACL knowledge stays
retrievable).
Sourcepub fn with_llm_provider(self, provider: Arc<dyn LlmProvider>) -> Self
pub fn with_llm_provider(self, provider: Arc<dyn LlmProvider>) -> Self
Inject a custom LlmProvider (e.g. a
MockLlmClient) so the
agent loop runs deterministically with no network / API key. This is
the test seam.
Sourcepub fn with_max_iterations(self, max: u32) -> Self
pub fn with_max_iterations(self, max: u32) -> Self
Cap on agent loop iterations (LLM call → tool calls → LLM call → …). Defaults to 8.
Sourcepub async fn run_turn(
&self,
conversation_id: &str,
user_message: &str,
) -> Result<TurnOutcome>
pub async fn run_turn( &self, conversation_id: &str, user_message: &str, ) -> Result<TurnOutcome>
Run one knowledge-grounded turn.
Drives the smooth-operator agent loop to completion, then returns the
final assistant text plus every AgentEvent emitted. The inbound
user message and the outbound reply are also persisted to the storage
adapter’s message log under conversation_id (best-effort: a persist
failure surfaces as an error so callers don’t silently lose history).
§Errors
Returns an error if the agent loop fails fatally or message persistence fails.
Auto Trait Implementations§
impl !RefUnwindSafe for KnowledgeChatRuntime
impl !UnwindSafe for KnowledgeChatRuntime
impl Freeze for KnowledgeChatRuntime
impl Send for KnowledgeChatRuntime
impl Sync for KnowledgeChatRuntime
impl Unpin for KnowledgeChatRuntime
impl UnsafeUnpin for KnowledgeChatRuntime
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> FutureExt for T
impl<T> FutureExt for T
Source§fn with_context(self, otel_cx: Context) -> WithContext<Self>
fn with_context(self, otel_cx: Context) -> WithContext<Self>
Source§fn with_current_context(self) -> WithContext<Self>
fn with_current_context(self) -> WithContext<Self>
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
Source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a tonic::Request