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>
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:
- Builds a message list from the conversation context (if provided) plus the user query.
- Calls the inference engine via
instrumented_generate()for telemetry tracking. - Returns the response as an
AgentResultwithturns=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:
- Builds the initial message list from context and the user query.
- Sends messages with tool definitions (OpenAI function-calling format) to the engine.
- If the engine responds with
tool_calls, theToolExecutordispatches each call. - Tool results are appended as
TOOLmessages and the loop continues. - If no
tool_callsare returned, the response is treated as the final answer. - The loop stops after
max_turnsiterations (default: 10), returning whatever content is available along with amax_turns_exceededmetadata 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:
- Checks transport health.
- Sends a
QUERYprotocol message through the transport. - If the response is a
TOOL_CALL, dispatches the tool locally viaToolExecutor. - Sends the tool result back as a
TOOL_RESULTmessage. - 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.