mirror of
https://github.com/open-jarvis/OpenJarvis.git
synced 2026-07-30 10:52:15 +00:00
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>
270 lines
10 KiB
Markdown
270 lines
10 KiB
Markdown
# 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.
|
|
|
|
```python
|
|
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.
|
|
|
|
```python
|
|
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:
|
|
|
|
```bash
|
|
jarvis ask --agent my-agent "Hello"
|
|
```
|
|
|
|
```python
|
|
response = j.ask("Hello", agent="my-agent")
|
|
```
|
|
|
|
---
|
|
|
|
## Using Agents
|
|
|
|
### Via CLI
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```python
|
|
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:
|
|
|
|
```python
|
|
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.
|