jeevesagent.agent
=================

.. py:module:: jeevesagent.agent

.. autoapi-nested-parse::

   The public :class:`Agent` class and its supporting machinery.



Submodules
----------

.. toctree::
   :maxdepth: 1

   /api/jeevesagent/agent/api/index


Classes
-------

.. autoapisummary::

   jeevesagent.agent.Agent


Package Contents
----------------

.. py:class:: 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)

   A fully-async, MCP-native, model-agnostic agent harness.


   .. py:method:: add_tool(item: jeevesagent.tools.registry.Tool | collections.abc.Callable[Ellipsis, object]) -> jeevesagent.tools.registry.Tool

      Register a tool after construction.

      Convenience for plugin-style code that adds tools after the
      ``Agent`` exists. Only works when the underlying tool host is
      an :class:`InProcessToolHost` (the default — and the only host
      that has a writable registry today).

      Returns the constructed :class:`Tool` so callers can introspect
      the auto-derived schema.



   .. py:method:: after_tool(fn: jeevesagent.security.hooks.PostToolHook) -> jeevesagent.security.hooks.PostToolHook

      Register a best-effort post-tool callback.



   .. py:method:: before_tool(fn: jeevesagent.security.hooks.PreToolHook) -> jeevesagent.security.hooks.PreToolHook

      Register a pre-tool hook. First denial wins; allow otherwise.



   .. py:method:: consolidate() -> int
      :async:


      Manually trigger memory consolidation.

      Returns the number of new facts the consolidator extracted,
      or ``0`` when 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.



   .. py:method:: 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
      :classmethod:


      Construct an ``Agent`` from 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``, custom ``Model``, 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")



   .. py:method:: 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
      :classmethod:


      Construct an ``Agent`` from a parsed config dict.

      Same shape as :meth:`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, a
      ``yaml.safe_load`` result, an HTTP API, etc.

      Recognised keys (all optional except ``instructions`` and
      ``model``):

      * ``instructions: str`` — required
      * ``model: str`` — required (or pass ``model=`` kwarg)
      * ``max_turns: int``
      * ``auto_consolidate: bool``
      * ``budget: dict`` with any of ``max_tokens``,
        ``max_input_tokens``, ``max_output_tokens``, ``max_cost_usd``,
        ``max_wall_clock_minutes``, ``soft_warning_at``



   .. py:method:: generate_graph(path: str | pathlib.Path | None = None, *, title: str | None = None) -> str
      :async:


      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 ``path`` is provided, also
      writes to disk — extension determines the format:

      * ``.mmd`` — raw Mermaid source
      * ``.md``  — Markdown with the diagram in a ``mermaid``
        fence (renders on GitHub, IDE markdown previews,
        Jupyter)
      * ``.png`` / ``.svg`` — rendered via ``mermaid.ink``;
        falls back to ``.mmd`` next 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).



   .. py:method:: recall(query: str, *, kind: str = 'episodic', limit: int = 5) -> list[Any]
      :async:


      Convenience wrapper around ``self.memory.recall(query, ...)``.

      Returns episodes matching ``query``. For semantic / fact-store
      recall, use ``self.memory.facts.recall_text(...)`` directly.



   .. py:method:: remove_tool(name: str) -> bool

      Unregister a tool by name. Returns ``True`` if a tool was
      removed, ``False`` if no tool with that name was registered.

      Same constraint as :meth:`add_tool`: only works with
      :class:`InProcessToolHost`.



   .. py:method:: 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
      :async:


      Resume a previously-interrupted run from its journal.

      Equivalent to ``agent.run(prompt, session_id=session_id, ...)``
      with the same kwarg surface as :meth:`run`. Exists as a
      separate method so the intent is explicit at the call site
      — when a durable :class:`Runtime` (e.g. :class:`SqliteRuntime`)
      is configured, completed steps replay from the journal
      instead of re-executing.



   .. py:method:: 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
      :async:


      Run the agent to completion and return its :class:`RunResult`.

      ``user_id`` is the namespace partition for memory recall and
      persistence — episodes and facts stored with one ``user_id``
      are never visible to a query scoped to a different ``user_id``.
      ``None`` is the "anonymous / single-tenant" bucket. See
      :class:`~jeevesagent.RunContext` for the partitioning
      contract.

      Pass ``session_id`` to resume a journaled run — when paired with
      a durable runtime (e.g. :class:`SqliteRuntime`), already-completed
      steps replay from the journal instead of re-executing. Without a
      durable runtime, ``session_id`` just labels the run.

      ``metadata`` is a free-form bag for application context the
      framework does not interpret (locale, request id, feature
      flags). Tools and hooks read it via
      ``get_run_context().metadata``.

      ``context`` accepts a fully-formed :class:`RunContext` instead
      of the individual kwargs — useful when passing context through
      multi-agent boundaries that received their parent's context as
      a single object. When both ``context`` and the individual
      kwargs are provided, the kwargs override the corresponding
      fields on ``context``.

      ``extra_tools`` injects additional :class:`Tool`\ s for this
      run only — the agent's configured ``ToolHost`` is 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's
      ``handoff(target, message)``) into a peer agent's loop without
      permanently mutating that agent's static configuration.

      ``emit`` is an awaitable callback invoked once per
      :class:`Event` produced during the run (model chunks, tool
      calls, tool results, architecture progress, errors, ...).
      Default ``None`` drops events on the floor (regular ``run``
      semantics — return only the final ``RunResult``). Multi-agent
      architectures pass an emit that forwards a sub-Agent's events
      into the parent's stream, so calls like ``await
      worker.run(prompt, emit=parent_send)`` surface the worker's
      token-by-token streaming to the outermost ``agent.stream(...)``
      consumer.

      ``output_schema`` requests a structured, validated final
      answer. Pass any Pydantic ``BaseModel`` subclass 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) populate :attr:`RunResult.parsed` with the
      validated instance. ``RunResult.output`` keeps the raw text
      so you can log or display it. Up to
      ``output_validation_retries`` extra 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 raises
      :class:`~jeevesagent.OutputValidationError`. Set retries to
      0 to fail fast.



   .. py:method:: 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]
      :async:


      Stream :class:`Event`\ s 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_id`` works the same as :meth:`run`'s — pass an
      existing one to resume against a durable runtime's journal.
      ``extra_tools`` works the same as :meth:`run`'s.



   .. py:method:: tools_list() -> list[str]
      :async:


      Return the names of all currently-registered tools.

      Convenience that works for any :class:`ToolHost`. Calls
      ``tool_host.list_tools()`` under the hood and returns just the
      names; use ``self.tool_host.list_tools()`` directly for the
      full :class:`ToolDef` records.



   .. py:method:: with_tool(fn: collections.abc.Callable[Ellipsis, object]) -> collections.abc.Callable[Ellipsis, object]

      Decorator-style equivalent of :meth:`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 :class:`InProcessToolHost`. Same constraint as
      :meth:`add_tool`: the host must be writable.



   .. py:property:: architecture
      :type: jeevesagent.architecture.Architecture


      The configured :class:`Architecture` strategy.

      Default is :class:`~jeevesagent.architecture.ReAct`. Pass
      ``architecture=`` to ``Agent(...)`` to override.


   .. py:property:: budget
      :type: jeevesagent.core.protocols.Budget


      The configured :class:`Budget`.


   .. py:property:: hooks
      :type: jeevesagent.core.protocols.HookHost



   .. py:property:: instructions
      :type: str


      The system prompt the agent runs with.

      Surfaced as a public property so multi-agent architectures
      (e.g. :class:`~jeevesagent.architecture.Supervisor`) can read
      each worker's intended role when composing instructions for
      the supervising model.


   .. py:property:: memory
      :type: jeevesagent.core.protocols.Memory


      The configured :class:`Memory` backend.


   .. py:property:: model
      :type: jeevesagent.core.protocols.Model


      The configured :class:`Model` adapter.


   .. py:property:: permissions
      :type: jeevesagent.core.protocols.Permissions


      The configured :class:`Permissions` policy.


   .. py:property:: runtime
      :type: jeevesagent.core.protocols.Runtime


      The configured :class:`Runtime`.


   .. py:property:: skills
      :type: Any | None


      The :class:`SkillRegistry` of skills registered on this
      agent (or ``None`` if no skills were configured). Useful for
      inspecting / mutating the skill set after construction.


   .. py:property:: tool_host
      :type: jeevesagent.core.protocols.ToolHost


      The configured :class:`ToolHost`.


