jeevesagent.agent.api¶
The public Agent class.
Conventions:
Pass a string of instructions for a working agent backed by sensible defaults:
EchoModel,InMemoryMemory,InProcRuntime,NoBudget,AllowAll,HookRegistry, an emptyInProcessToolHost.Pass
tools=[fn_or_Tool, ...]to register Python callables; the agent wraps them in an in-processToolHost.Override any subsystem by passing a concrete implementation of the matching protocol from
jeevesagent.core.protocols.
Two execution surfaces share a single internal loop:
Agent.run()runs to completion and returns aRunResult.Agent.stream()returns anAsyncIterator[Event]of milestones as they happen — STARTED, MODEL_CHUNK, TOOL_CALL, TOOL_RESULT, BUDGET_WARNING/EXCEEDED, ERROR, COMPLETED.
Internally, _loop() accepts an emit callback and threads it
through every milestone. run() passes a no-op emit; stream()
pipes events through an anyio.create_memory_object_stream() so a
slow consumer applies backpressure to the loop instead of buffering
unboundedly.
Attributes¶
Classes¶
A fully-async, MCP-native, model-agnostic agent harness. |
Module Contents¶
- class jeevesagent.agent.api.Agent(instructions: str, *, model: jeevesagent.core.protocols.Model | str | None = None, memory: jeevesagent.core.protocols.Memory | None = None, runtime: jeevesagent.core.protocols.Runtime | None = None, budget: jeevesagent.core.protocols.Budget | None = None, permissions: jeevesagent.core.protocols.Permissions | None = None, hooks: jeevesagent.security.hooks.HookRegistry | None = None, tools: list[jeevesagent.tools.registry.Tool | collections.abc.Callable[Ellipsis, object]] | jeevesagent.core.protocols.ToolHost | jeevesagent.tools.registry.Tool | collections.abc.Callable[Ellipsis, object] | None = None, telemetry: jeevesagent.core.protocols.Telemetry | None = None, audit_log: jeevesagent.security.audit.AuditLog | None = None, max_turns: int = DEFAULT_MAX_TURNS, auto_consolidate: bool = False, architecture: jeevesagent.architecture.Architecture | str | None = None, skills: list[Any] | None = None, retry_policy: jeevesagent.governance.retry.RetryPolicy | None = None)[source]¶
A fully-async, MCP-native, model-agnostic agent harness.
- add_tool(item: jeevesagent.tools.registry.Tool | collections.abc.Callable[Ellipsis, object]) jeevesagent.tools.registry.Tool[source]¶
Register a tool after construction.
Convenience for plugin-style code that adds tools after the
Agentexists. Only works when the underlying tool host is anInProcessToolHost(the default — and the only host that has a writable registry today).Returns the constructed
Toolso callers can introspect the auto-derived schema.
- after_tool(fn: jeevesagent.security.hooks.PostToolHook) jeevesagent.security.hooks.PostToolHook[source]¶
Register a best-effort post-tool callback.
- before_tool(fn: jeevesagent.security.hooks.PreToolHook) jeevesagent.security.hooks.PreToolHook[source]¶
Register a pre-tool hook. First denial wins; allow otherwise.
- async consolidate() int[source]¶
Manually trigger memory consolidation.
Returns the number of new facts the consolidator extracted, or
0when the memory backend doesn’t expose a fact store.Useful when
auto_consolidate=False(the default) and you want to batch consolidation at a controlled cadence — e.g. once a day, or before shutdown.
- classmethod from_config(path: str | pathlib.Path, *, model: jeevesagent.core.protocols.Model | None = None, memory: jeevesagent.core.protocols.Memory | None = None, runtime: jeevesagent.core.protocols.Runtime | None = None, tools: list[jeevesagent.tools.registry.Tool | collections.abc.Callable[Ellipsis, object]] | jeevesagent.core.protocols.ToolHost | None = None) Agent[source]¶
Construct an
Agentfrom a TOML config file.Designed for ops/devops users who want declarative agent config separate from code. Supports the textual / numeric bits — instructions, model spec (string), max_turns, auto_consolidate, budget — and lets callers pass concrete instances for the things TOML can’t reasonably express (real
Memory,Runtime, customModel, tools).Example
agent.toml:instructions = "You are a research assistant." model = "claude-opus-4-7" max_turns = 100 auto_consolidate = true [budget] max_tokens = 200_000 max_cost_usd = 5.0 max_wall_clock_minutes = 10 soft_warning_at = 0.8
Then:
agent = Agent.from_config("agent.toml")
- classmethod from_dict(cfg: dict[str, Any], *, model: jeevesagent.core.protocols.Model | None = None, memory: jeevesagent.core.protocols.Memory | None = None, runtime: jeevesagent.core.protocols.Runtime | None = None, tools: list[jeevesagent.tools.registry.Tool | collections.abc.Callable[Ellipsis, object]] | jeevesagent.core.protocols.ToolHost | None = None) Agent[source]¶
Construct an
Agentfrom a parsed config dict.Same shape as
from_config()but skips the file read. Useful when the config comes from somewhere other than a TOML file — environment variables, a Pydantic settings model, ayaml.safe_loadresult, an HTTP API, etc.Recognised keys (all optional except
instructionsandmodel):instructions: str— requiredmodel: str— required (or passmodel=kwarg)max_turns: intauto_consolidate: boolbudget: dictwith any ofmax_tokens,max_input_tokens,max_output_tokens,max_cost_usd,max_wall_clock_minutes,soft_warning_at
- async generate_graph(path: str | pathlib.Path | None = None, *, title: str | None = None) str[source]¶
Render this agent’s structure as a Mermaid graph.
Walks the agent + its architecture + all sub-agents + every agent’s tools, producing a graph that captures the full team, tool attachments, and architecture-specific relationships (delegate / handoff / classify / etc.).
Returns the Mermaid text. If
pathis provided, also writes to disk — extension determines the format:.mmd— raw Mermaid source.md— Markdown with the diagram in amermaidfence (renders on GitHub, IDE markdown previews, Jupyter).png/.svg— rendered viamermaid.ink; falls back to.mmdnext to the path on network failure
Example:
mermaid_text = await agent.generate_graph("graph.md") print(mermaid_text)
Pass
title=to override the diagram title (defaults to the file’s stem, or"Agent"if no path is given).
- async recall(query: str, *, kind: str = 'episodic', limit: int = 5) list[Any][source]¶
Convenience wrapper around
self.memory.recall(query, ...).Returns episodes matching
query. For semantic / fact-store recall, useself.memory.facts.recall_text(...)directly.
- remove_tool(name: str) bool[source]¶
Unregister a tool by name. Returns
Trueif a tool was removed,Falseif no tool with that name was registered.Same constraint as
add_tool(): only works withInProcessToolHost.
- async resume(session_id: str, prompt: str, *, user_id: str | None = None, metadata: collections.abc.Mapping[str, Any] | None = None, context: jeevesagent.core.context.RunContext | None = None, extra_tools: list[jeevesagent.tools.registry.Tool] | None = None, emit: Emit | None = None, output_schema: type[pydantic.BaseModel] | None = None, output_validation_retries: int = 1) jeevesagent.core.types.RunResult[source]¶
Resume a previously-interrupted run from its journal.
Equivalent to
agent.run(prompt, session_id=session_id, ...)with the same kwarg surface asrun(). Exists as a separate method so the intent is explicit at the call site — when a durableRuntime(e.g.SqliteRuntime) is configured, completed steps replay from the journal instead of re-executing.
- async run(prompt: str, *, user_id: str | None = None, session_id: str | None = None, metadata: collections.abc.Mapping[str, Any] | None = None, context: jeevesagent.core.context.RunContext | None = None, extra_tools: list[jeevesagent.tools.registry.Tool] | None = None, emit: Emit | None = None, output_schema: type[pydantic.BaseModel] | None = None, output_validation_retries: int = 1) jeevesagent.core.types.RunResult[source]¶
Run the agent to completion and return its
RunResult.user_idis the namespace partition for memory recall and persistence — episodes and facts stored with oneuser_idare never visible to a query scoped to a differentuser_id.Noneis the “anonymous / single-tenant” bucket. SeeRunContextfor the partitioning contract.Pass
session_idto resume a journaled run — when paired with a durable runtime (e.g.SqliteRuntime), already-completed steps replay from the journal instead of re-executing. Without a durable runtime,session_idjust labels the run.metadatais a free-form bag for application context the framework does not interpret (locale, request id, feature flags). Tools and hooks read it viaget_run_context().metadata.contextaccepts a fully-formedRunContextinstead of the individual kwargs — useful when passing context through multi-agent boundaries that received their parent’s context as a single object. When bothcontextand the individual kwargs are provided, the kwargs override the corresponding fields oncontext.extra_toolsinjects additionalTools for this run only — the agent’s configuredToolHostis wrapped so the model sees the extras alongside whatever tools were registered at construction. Used by multi-agent architectures that need to inject coordination tools (e.g. Swarm’shandoff(target, message)) into a peer agent’s loop without permanently mutating that agent’s static configuration.emitis an awaitable callback invoked once perEventproduced during the run (model chunks, tool calls, tool results, architecture progress, errors, …). DefaultNonedrops events on the floor (regularrunsemantics — return only the finalRunResult). Multi-agent architectures pass an emit that forwards a sub-Agent’s events into the parent’s stream, so calls likeawait worker.run(prompt, emit=parent_send)surface the worker’s token-by-token streaming to the outermostagent.stream(...)consumer.output_schemarequests a structured, validated final answer. Pass any PydanticBaseModelsubclass and the framework will (1) append a JSON-schema directive to the system prompt instructing the model to emit a final answer that matches, (2) parse the final assistant text against the schema, and (3) populateRunResult.parsedwith the validated instance.RunResult.outputkeeps the raw text so you can log or display it. Up tooutput_validation_retriesextra turns are spent recovering from a parse failure (the model is given the validation error as feedback and asked to try again); if it still fails after the retry budget, the run raisesOutputValidationError. Set retries to 0 to fail fast.
- async stream(prompt: str, *, user_id: str | None = None, session_id: str | None = None, metadata: collections.abc.Mapping[str, Any] | None = None, context: jeevesagent.core.context.RunContext | None = None, extra_tools: list[jeevesagent.tools.registry.Tool] | None = None, output_schema: type[pydantic.BaseModel] | None = None, output_validation_retries: int = 1) collections.abc.AsyncIterator[jeevesagent.core.types.Event][source]¶
Stream
Events as the loop produces them.The loop runs as a background task; events are pushed through a bounded memory stream so a slow consumer applies backpressure. Breaking out of the iteration cancels the producer cleanly.
session_idworks the same asrun()’s — pass an existing one to resume against a durable runtime’s journal.extra_toolsworks the same asrun()’s.
- async tools_list() list[str][source]¶
Return the names of all currently-registered tools.
Convenience that works for any
ToolHost. Callstool_host.list_tools()under the hood and returns just the names; useself.tool_host.list_tools()directly for the fullToolDefrecords.
- with_tool(fn: collections.abc.Callable[Ellipsis, object]) collections.abc.Callable[Ellipsis, object][source]¶
Decorator-style equivalent of
add_tool().Usage:
@agent.with_tool async def search(query: str) -> str: '''Search a knowledge base.''' return f"results for {query}"
Returns the original function unchanged (so it can still be called normally), and registers it as a tool on the agent’s underlying
InProcessToolHost. Same constraint asadd_tool(): the host must be writable.
- property architecture: jeevesagent.architecture.Architecture¶
The configured
Architecturestrategy.Default is
ReAct. Passarchitecture=toAgent(...)to override.
- property budget: jeevesagent.core.protocols.Budget¶
The configured
Budget.
- property hooks: jeevesagent.core.protocols.HookHost¶
- property instructions: str¶
The system prompt the agent runs with.
Surfaced as a public property so multi-agent architectures (e.g.
Supervisor) can read each worker’s intended role when composing instructions for the supervising model.
- property memory: jeevesagent.core.protocols.Memory¶
The configured
Memorybackend.
- property model: jeevesagent.core.protocols.Model¶
The configured
Modeladapter.
- property permissions: jeevesagent.core.protocols.Permissions¶
The configured
Permissionspolicy.
- property runtime: jeevesagent.core.protocols.Runtime¶
The configured
Runtime.
- property skills: Any | None¶
The
SkillRegistryof skills registered on this agent (orNoneif no skills were configured). Useful for inspecting / mutating the skill set after construction.
- property tool_host: jeevesagent.core.protocols.ToolHost¶
The configured
ToolHost.
- jeevesagent.agent.api.DEFAULT_MAX_TURNS = 50¶
- jeevesagent.agent.api.DEFAULT_STREAM_BUFFER = 128¶
- jeevesagent.agent.api.Emit¶