Files
OpenJarvis/docs/user-guide/agents.md
T
Jon Saad-FalconandClaude Opus 4.6 f75afefcfb Add MkDocs Material documentation site with 40 pages and auto-generated API reference
Sets up a complete documentation website with 7 navigable sections (Home, Getting
Started, User Guide, Architecture, API Reference, Deployment, Development), light/dark
mode, search, code copy, and Mermaid diagram support. API reference pages use
mkdocstrings to auto-generate docs from source docstrings. GitHub Actions workflow
deploys to GitHub Pages on push to main.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 06:09:36 +00:00

10 KiB

Agents

Agents are the agentic logic layer of OpenJarvis. They determine how a query is processed -- whether it goes directly to a model, through a tool-calling loop, or via an external agent runtime. All agents implement the BaseAgent ABC and are registered via the AgentRegistry.

Overview

Agent Registry Key Tools Multi-turn Description
SimpleAgent simple No No Single-turn query-to-response
OrchestratorAgent orchestrator Yes Yes Multi-turn tool-calling loop
OpenClawAgent openclaw Yes Yes External agent via HTTP or subprocess
CustomAgent custom -- -- Template for user-defined agents

BaseAgent ABC

All agents extend the abstract BaseAgent class.

from abc import ABC, abstractmethod
from openjarvis.agents._stubs import AgentContext, AgentResult

class BaseAgent(ABC):
    agent_id: str

    @abstractmethod
    def run(
        self,
        input: str,
        context: AgentContext | None = None,
        **kwargs,
    ) -> AgentResult:
        """Execute the agent on the given input."""

AgentContext

The runtime context handed to an agent on each invocation.

Field Type Description
conversation Conversation Message history (pre-filled with context if memory injection is active)
tools list[str] Tool names available to the agent
memory_results list[Any] Pre-fetched memory retrieval results
metadata dict[str, Any] Arbitrary metadata for the run

AgentResult

The result returned after an agent completes a run.

Field Type Description
content str The final response text
tool_results list[ToolResult] Results from tool executions during the run
turns int Number of turns (inference calls) taken
metadata dict[str, Any] Arbitrary metadata about the run

SimpleAgent

The SimpleAgent is a single-turn agent that sends the query directly to the inference engine and returns the response. It does not support tool calling.

How it works:

  1. Builds a message list from the conversation context (if provided) plus the user query.
  2. Calls the inference engine via instrumented_generate() for telemetry tracking.
  3. Returns the response as an AgentResult with turns=1.

Constructor parameters:

Parameter Type Default Description
engine InferenceEngine -- The inference engine to use
model str -- Model identifier
bus EventBus None Event bus for telemetry
temperature float 0.7 Sampling temperature
max_tokens int 1024 Maximum tokens to generate

When to use: For straightforward question-answering without tool calling or multi-turn reasoning.


OrchestratorAgent

The OrchestratorAgent is a multi-turn agent that implements a tool-calling loop. It is the primary agent for queries that require computation, knowledge retrieval, or structured reasoning.

How it works:

  1. Builds the initial message list from context and the user query.
  2. Sends messages with tool definitions (OpenAI function-calling format) to the engine.
  3. If the engine responds with tool_calls, the ToolExecutor dispatches each call.
  4. Tool results are appended as TOOL messages and the loop continues.
  5. If no tool_calls are returned, the response is treated as the final answer.
  6. The loop stops after max_turns iterations (default: 10), returning whatever content is available along with a max_turns_exceeded metadata flag.

Constructor parameters:

Parameter Type Default Description
engine InferenceEngine -- The inference engine to use
model str -- Model identifier
tools list[BaseTool] [] Tool instances to make available
bus EventBus None Event bus for telemetry
max_turns int 10 Maximum number of tool-calling turns
temperature float 0.7 Sampling temperature
max_tokens int 1024 Maximum tokens to generate

When to use: For queries that need calculation, memory search, sub-model calls, file reading, or multi-step reasoning.

!!! info "Tool-Calling Loop" The orchestrator follows the OpenAI function-calling convention. The engine must support returning tool_calls in its response for the loop to engage. If tools are provided but the engine does not return any tool calls, the agent behaves like a single-turn agent.


OpenClawAgent

The OpenClawAgent wraps the OpenClaw Pi agent runtime, communicating via either HTTP or subprocess transport. It supports tool calling through the OpenClaw protocol.

How it works:

  1. Checks transport health.
  2. Sends a QUERY protocol message through the transport.
  3. If the response is a TOOL_CALL, dispatches the tool locally via ToolExecutor.
  4. Sends the tool result back as a TOOL_RESULT message.
  5. Continues the tool-call loop until the response is a final answer or error (up to 10 turns).

Constructor parameters:

Parameter Type Default Description
engine Any None Inference engine (fallback/provider)
model str "" Model identifier
transport OpenClawTransport None Pre-configured transport (overrides mode)
mode str "http" Transport mode: "http" or "subprocess"
bus EventBus None Event bus for telemetry

Transport modes:

  • HTTP (HttpTransport): Sends HTTP POST requests to an OpenClaw server.
  • Subprocess (SubprocessTransport): Spawns a Node.js process and communicates via stdin/stdout using JSON-line protocol.

!!! warning "Node.js Requirement" The subprocess transport mode requires Node.js 22+ to be installed on the system.


CustomAgent

The CustomAgent is a template for building user-defined agents. It raises NotImplementedError by default -- subclass it and override run() to implement your logic.

from openjarvis.agents._stubs import AgentContext, AgentResult, BaseAgent
from openjarvis.core.registry import AgentRegistry


@AgentRegistry.register("my-agent")
class MyAgent(BaseAgent):
    agent_id = "my-agent"

    def __init__(self, engine, model, **kwargs):
        self._engine = engine
        self._model = model

    def run(self, input: str, context: AgentContext | None = None, **kwargs) -> AgentResult:
        # Your custom logic here
        result = self._engine.generate(
            [{"role": "user", "content": input}],
            model=self._model,
        )
        return AgentResult(
            content=result.get("content", ""),
            turns=1,
        )

After registration, you can use your custom agent via the CLI or SDK:

jarvis ask --agent my-agent "Hello"
response = j.ask("Hello", agent="my-agent")

Using Agents

Via CLI

# Simple agent
jarvis ask --agent simple "What is the capital of France?"

# Orchestrator with tools
jarvis ask --agent orchestrator --tools calculator,think "What is sqrt(256)?"

# OpenClaw agent
jarvis ask --agent openclaw "Tell me a story"

Via Python SDK

from openjarvis import Jarvis

j = Jarvis()

# Simple agent
response = j.ask("Hello", agent="simple")

# Orchestrator with tools
response = j.ask(
    "Calculate 15% of 340",
    agent="orchestrator",
    tools=["calculator"],
)

# Full result with tool details
result = j.ask_full(
    "What is the square root of 144?",
    agent="orchestrator",
    tools=["calculator", "think"],
)
print(result["content"])
print(result["turns"])
print(result["tool_results"])

j.close()

Agent Registration

Agents are registered via the @AgentRegistry.register() decorator. This makes them discoverable by name at runtime:

from openjarvis.core.registry import AgentRegistry

# Check if an agent is registered
AgentRegistry.contains("orchestrator")  # True

# Get the agent class
agent_cls = AgentRegistry.get("orchestrator")

# List all registered agent keys
AgentRegistry.keys()  # ["simple", "orchestrator", "openclaw", "custom"]

Event Bus Integration

All agents publish events on the EventBus when a bus is provided:

Event When
AGENT_TURN_START At the beginning of a run
AGENT_TURN_END At the end of a run (includes turn count)
INFERENCE_START Before each engine call (orchestrator)
INFERENCE_END After each engine call (orchestrator)
TOOL_CALL_START Before each tool execution (openclaw)
TOOL_CALL_END After each tool execution (openclaw)

These events enable the telemetry and trace systems to record detailed interaction data automatically.