jeevesagent.core.protocols¶
Protocol definitions for every module boundary.
These structural types are the contract surface of the harness. Every implementation — first-party or third-party — satisfies one of these. The loop and the agent only depend on the protocols, never on concrete implementations.
The protocols are intentionally async-only: every method that performs
I/O is a coroutine, every stream is an AsyncIterator, every
resource is an AsyncContextManager.
Classes¶
Resource governance — tokens, calls, cost, wall clock. |
|
Text-to-vector embedding model used by the memory subsystem. |
|
Aggregator over user-registered lifecycle callbacks. |
|
Tiered memory: working blocks, episodic store, semantic graph. |
|
LLM provider interface. One adapter per lab (Anthropic, OpenAI, ...). |
|
Decides whether a tool call is allowed. |
|
Durable execution. Wraps every side effect in a journal entry. |
|
Handle to an open durable session held by a |
|
Isolation layer for tool execution. |
|
Resolution and redaction of named secrets. |
|
OpenTelemetry-compatible tracing/metrics surface. |
|
MCP-aware tool registry. Lazy-loads schemas on demand. |
Module Contents¶
- class jeevesagent.core.protocols.Budget[source]¶
Bases:
ProtocolResource governance — tokens, calls, cost, wall clock.
- async allows_step() jeevesagent.core.types.BudgetStatus[source]¶
- class jeevesagent.core.protocols.Embedder[source]¶
Bases:
ProtocolText-to-vector embedding model used by the memory subsystem.
- class jeevesagent.core.protocols.HookHost[source]¶
Bases:
ProtocolAggregator over user-registered lifecycle callbacks.
- async on_event(event: jeevesagent.core.types.Event) None[source]¶
- async post_tool(call: jeevesagent.core.types.ToolCall, result: jeevesagent.core.types.ToolResult) None[source]¶
- async pre_tool(call: jeevesagent.core.types.ToolCall) jeevesagent.core.types.PermissionDecision[source]¶
- class jeevesagent.core.protocols.Memory[source]¶
Bases:
ProtocolTiered memory: working blocks, episodic store, semantic graph.
- async append_block(name: str, content: str) None[source]¶
Append to a named block, creating it if absent.
- async recall(query: str, *, kind: str = 'episodic', limit: int = 5, time_range: tuple[datetime.datetime, datetime.datetime] | None = None, user_id: str | None = None) list[jeevesagent.core.types.Episode][source]¶
Retrieve episodes (or facts, when
kind='semantic').When
user_idis supplied, results are restricted to episodes stored with that exactuser_idvalue.Noneis its own bucket (the “anonymous / single-tenant” namespace) — episodes stored withuser_id=Noneare never visible to a query withuser_id="alice"and vice versa. Backends MUST honour this filter to preserve the framework’s multi-tenant safety contract.
- async recall_facts(query: str, *, limit: int = 5, valid_at: datetime.datetime | None = None, user_id: str | None = None) list[jeevesagent.core.types.Fact][source]¶
Retrieve bi-temporal facts matching
query.Backends that don’t expose a fact store return
[]. The agent loop calls this directly rather than duck-typing onmemory.factsso backends without fact support don’t need any opt-out mechanism.user_idfilters by namespace partition with the same semantics asrecall():Noneis its own bucket and does not cross-contaminate with non-None values.
- async remember(episode: jeevesagent.core.types.Episode) str[source]¶
Persist an episode. Returns the episode ID.
- async session_messages(session_id: str, *, user_id: str | None = None, limit: int = 20) list[jeevesagent.core.types.Message][source]¶
Return the most-recent
limituser/assistant turns from the conversation identified bysession_id, in order (oldest first).This is the conversation-continuity primitive — the agent loop calls it at the top of every run so that reusing a
session_idactually continues the chat (the model sees previous turns as realMessagehistory) rather than starting fresh and relying solely on semantic recall.user_idMUST be respected by backends as a hard namespace partition: messages persisted under oneuser_idare never visible to a query scoped to a different one. Backends without persisted message logs return[]— the agent loop falls back to the semantic-recall path in that case.
- async working() list[jeevesagent.core.types.MemoryBlock][source]¶
All in-context blocks. Pinned to every prompt.
- class jeevesagent.core.protocols.Model[source]¶
Bases:
ProtocolLLM provider interface. One adapter per lab (Anthropic, OpenAI, …).
The required surface is
stream(...)— every adapter must implement it. Adapters MAY additionally overridecomplete(...)with a non-streaming (single-shot) call; if not,completefalls back to consuming the stream internally and assembling the full response, which is correct but slower (per-chunk wire + parsing overhead). Architectures usecompleteon the non-streaming hot path (agent.run()) andstreamwhen a consumer is reading fromagent.stream().- stream(messages: list[jeevesagent.core.types.Message], *, tools: list[jeevesagent.core.types.ToolDef] | None = None, temperature: float = 1.0, max_tokens: int | None = None) collections.abc.AsyncIterator[jeevesagent.core.types.ModelChunk][source]¶
Stream completion chunks. Each chunk is text, tool_call, or finish.
- class jeevesagent.core.protocols.Permissions[source]¶
Bases:
ProtocolDecides whether a tool call is allowed.
- async check(call: jeevesagent.core.types.ToolCall, *, context: collections.abc.Mapping[str, Any]) jeevesagent.core.types.PermissionDecision[source]¶
- class jeevesagent.core.protocols.Runtime[source]¶
Bases:
ProtocolDurable execution. Wraps every side effect in a journal entry.
- session(session_id: str) contextlib.AbstractAsyncContextManager[RuntimeSession][source]¶
Open or resume a durable session.
- async signal(session_id: str, name: str, payload: Any) None[source]¶
Send an external signal (e.g., human approval) to a session.
- async step(name: str, fn: collections.abc.Callable[Ellipsis, collections.abc.Awaitable[Any]], *args: Any, idempotency_key: str | None = None, **kwargs: Any) Any[source]¶
Execute
fnas a journaled step. Replays cached on resume.
- stream_step(name: str, fn: collections.abc.Callable[Ellipsis, collections.abc.AsyncIterator[Any]], *args: Any, **kwargs: Any) collections.abc.AsyncIterator[Any][source]¶
Execute a streaming step. Replays the aggregate on resume.
- class jeevesagent.core.protocols.RuntimeSession[source]¶
Bases:
ProtocolHandle to an open durable session held by a
Runtime.
- class jeevesagent.core.protocols.Sandbox[source]¶
Bases:
ProtocolIsolation layer for tool execution.
- async execute(tool: jeevesagent.core.types.ToolDef, args: collections.abc.Mapping[str, Any]) jeevesagent.core.types.ToolResult[source]¶
- with_filesystem(root: str) contextlib.AbstractAsyncContextManager[None][source]¶
Temporary filesystem sandbox for the duration of the context.
- class jeevesagent.core.protocols.Secrets[source]¶
Bases:
ProtocolResolution and redaction of named secrets.
- class jeevesagent.core.protocols.Telemetry[source]¶
Bases:
ProtocolOpenTelemetry-compatible tracing/metrics surface.
- trace(name: str, **attrs: Any) contextlib.AbstractAsyncContextManager[jeevesagent.core.types.Span][source]¶
- class jeevesagent.core.protocols.ToolHost[source]¶
Bases:
ProtocolMCP-aware tool registry. Lazy-loads schemas on demand.
- async call(tool: str, args: collections.abc.Mapping[str, Any], *, call_id: str = '') jeevesagent.core.types.ToolResult[source]¶
Invoke
toolwithargs. Thecall_idis propagated into the returnedToolResultso the loop can correlate results with the originating model-emitted call.
- watch() collections.abc.AsyncIterator[jeevesagent.core.types.ToolEvent][source]¶
Notifications when the tool list changes (MCP listChanged).