orbitx 0.2.9 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Readme.md +478 -456
- package/dist/agents/backend.d.ts +4 -0
- package/dist/agents/backend.d.ts.map +1 -0
- package/dist/agents/backend.js +54 -0
- package/dist/agents/backend.js.map +1 -0
- package/dist/agents/frontend.d.ts +4 -0
- package/dist/agents/frontend.d.ts.map +1 -0
- package/dist/agents/frontend.js +50 -0
- package/dist/agents/frontend.js.map +1 -0
- package/dist/agents/index.d.ts +10 -0
- package/dist/agents/index.d.ts.map +1 -0
- package/dist/agents/index.js +22 -0
- package/dist/agents/index.js.map +1 -0
- package/dist/agents/planner.d.ts +4 -0
- package/dist/agents/planner.d.ts.map +1 -0
- package/dist/agents/planner.js +86 -0
- package/dist/agents/planner.js.map +1 -0
- package/dist/agents/protocol.d.ts +5 -0
- package/dist/agents/protocol.d.ts.map +1 -0
- package/dist/agents/protocol.js +70 -0
- package/dist/agents/protocol.js.map +1 -0
- package/dist/agents/reasoner.d.ts +5 -0
- package/dist/agents/reasoner.d.ts.map +1 -0
- package/dist/agents/reasoner.js +96 -0
- package/dist/agents/reasoner.js.map +1 -0
- package/dist/agents/research.d.ts +4 -0
- package/dist/agents/research.d.ts.map +1 -0
- package/dist/agents/research.js +28 -0
- package/dist/agents/research.js.map +1 -0
- package/dist/agents/tester.d.ts +4 -0
- package/dist/agents/tester.d.ts.map +1 -0
- package/dist/agents/tester.js +70 -0
- package/dist/agents/tester.js.map +1 -0
- package/dist/core/agent-definition.d.ts +61 -0
- package/dist/core/agent-definition.d.ts.map +1 -0
- package/dist/core/agent-definition.js +82 -0
- package/dist/core/agent-definition.js.map +1 -0
- package/dist/core/ai-provider.d.ts +3 -0
- package/dist/core/ai-provider.d.ts.map +1 -1
- package/dist/core/ai-provider.js.map +1 -1
- package/dist/core/anthropic-provider.d.ts +1 -0
- package/dist/core/anthropic-provider.d.ts.map +1 -1
- package/dist/core/anthropic-provider.js +3 -0
- package/dist/core/anthropic-provider.js.map +1 -1
- package/dist/core/base-agent.d.ts +51 -28
- package/dist/core/base-agent.d.ts.map +1 -1
- package/dist/core/base-agent.js +118 -26
- package/dist/core/base-agent.js.map +1 -1
- package/dist/core/deepseek-provider.d.ts +1 -0
- package/dist/core/deepseek-provider.d.ts.map +1 -1
- package/dist/core/deepseek-provider.js +3 -0
- package/dist/core/deepseek-provider.js.map +1 -1
- package/dist/core/mcp-computer.d.ts +14 -1
- package/dist/core/mcp-computer.d.ts.map +1 -1
- package/dist/core/mcp-computer.js +352 -71
- package/dist/core/mcp-computer.js.map +1 -1
- package/dist/core/ollama-provider.d.ts +1 -0
- package/dist/core/ollama-provider.d.ts.map +1 -1
- package/dist/core/ollama-provider.js +3 -0
- package/dist/core/ollama-provider.js.map +1 -1
- package/dist/core/openai-provider.d.ts +1 -0
- package/dist/core/openai-provider.d.ts.map +1 -1
- package/dist/core/openai-provider.js +3 -0
- package/dist/core/openai-provider.js.map +1 -1
- package/dist/core/swarm-base.d.ts +88 -0
- package/dist/core/swarm-base.d.ts.map +1 -0
- package/dist/core/swarm-base.js +427 -0
- package/dist/core/swarm-base.js.map +1 -0
- package/dist/index.d.ts +7 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -3
- package/dist/index.js.map +1 -1
- package/dist/tests/agents/default-agents.test.d.ts +2 -0
- package/dist/tests/agents/default-agents.test.d.ts.map +1 -0
- package/dist/tests/agents/default-agents.test.js +106 -0
- package/dist/tests/agents/default-agents.test.js.map +1 -0
- package/dist/tests/core/agent-definition.test.d.ts +2 -0
- package/dist/tests/core/agent-definition.test.d.ts.map +1 -0
- package/dist/tests/core/agent-definition.test.js +99 -0
- package/dist/tests/core/agent-definition.test.js.map +1 -0
- package/dist/tests/core/scripted-provider.d.ts +38 -0
- package/dist/tests/core/scripted-provider.d.ts.map +1 -0
- package/dist/tests/core/scripted-provider.js +85 -0
- package/dist/tests/core/scripted-provider.js.map +1 -0
- package/dist/tests/core/swarm-base.test.d.ts +2 -0
- package/dist/tests/core/swarm-base.test.d.ts.map +1 -0
- package/dist/tests/core/swarm-base.test.js +387 -0
- package/dist/tests/core/swarm-base.test.js.map +1 -0
- package/dist/tests/index.d.ts +3 -0
- package/dist/tests/index.d.ts.map +1 -1
- package/dist/tests/index.js +3 -0
- package/dist/tests/index.js.map +1 -1
- package/dist/tests/tools/agent/agent-tools.test.js +225 -153
- package/dist/tests/tools/agent/agent-tools.test.js.map +1 -1
- package/dist/tools/agent/active.d.ts +5 -0
- package/dist/tools/agent/active.d.ts.map +1 -0
- package/dist/tools/agent/active.js +40 -0
- package/dist/tools/agent/active.js.map +1 -0
- package/dist/tools/agent/fire.d.ts +5 -0
- package/dist/tools/agent/fire.d.ts.map +1 -0
- package/dist/tools/agent/fire.js +38 -0
- package/dist/tools/agent/fire.js.map +1 -0
- package/dist/tools/agent/hire.d.ts +2 -2
- package/dist/tools/agent/hire.d.ts.map +1 -1
- package/dist/tools/agent/hire.js +43 -10
- package/dist/tools/agent/hire.js.map +1 -1
- package/dist/tools/agent/index.d.ts +22 -19
- package/dist/tools/agent/index.d.ts.map +1 -1
- package/dist/tools/agent/index.js +29 -21
- package/dist/tools/agent/index.js.map +1 -1
- package/dist/tools/agent/prompt.d.ts +2 -2
- package/dist/tools/agent/prompt.d.ts.map +1 -1
- package/dist/tools/agent/prompt.js +19 -53
- package/dist/tools/agent/prompt.js.map +1 -1
- package/dist/tools/agent/registry.d.ts +74 -24
- package/dist/tools/agent/registry.d.ts.map +1 -1
- package/dist/tools/agent/registry.js +93 -48
- package/dist/tools/agent/registry.js.map +1 -1
- package/dist/tools/agent/report-group.d.ts +5 -0
- package/dist/tools/agent/report-group.d.ts.map +1 -0
- package/dist/tools/agent/report-group.js +50 -0
- package/dist/tools/agent/report-group.js.map +1 -0
- package/dist/tools/agent/report-parent.d.ts +5 -0
- package/dist/tools/agent/report-parent.d.ts.map +1 -0
- package/dist/tools/agent/report-parent.js +36 -0
- package/dist/tools/agent/report-parent.js.map +1 -0
- package/dist/tools/agent/types.d.ts +5 -0
- package/dist/tools/agent/types.d.ts.map +1 -0
- package/dist/tools/agent/types.js +17 -0
- package/dist/tools/agent/types.js.map +1 -0
- package/docs/agents.md +173 -228
- package/docs/api-reference.md +9 -4
- package/docs/getting-started.md +78 -78
- package/docs/index.md +24 -23
- package/docs/mcp-architecture.md +29 -6
- package/docs/providers.md +258 -254
- package/docs/skills.md +0 -1
- package/docs/streaming.md +133 -133
- package/docs/swarm.md +503 -0
- package/docs/tools.md +214 -212
- package/package.json +1 -1
package/docs/tools.md
CHANGED
|
@@ -1,212 +1,214 @@
|
|
|
1
|
-
# Tools
|
|
2
|
-
|
|
3
|
-
## The `MCPTool` shape
|
|
4
|
-
|
|
5
|
-
Every tool — built-in or custom — is an `MCPTool` instance (`src/core/mcp.ts`):
|
|
6
|
-
|
|
7
|
-
```ts
|
|
8
|
-
new MCPTool({
|
|
9
|
-
name: string;
|
|
10
|
-
description: string;
|
|
11
|
-
inputs: {
|
|
12
|
-
name: string;
|
|
13
|
-
type: "number" | "string" | "boolean" | "object" | "array";
|
|
14
|
-
description: string;
|
|
15
|
-
required?: boolean;
|
|
16
|
-
default?: any;
|
|
17
|
-
}[];
|
|
18
|
-
stopIterationAfterUsingThisTool?: boolean; // default false
|
|
19
|
-
execute: (
|
|
20
|
-
envID: string,
|
|
21
|
-
inputs: Record<string, any>,
|
|
22
|
-
toolCallId?: string,
|
|
23
|
-
mcp?: MCP
|
|
24
|
-
) => Promise<any>;
|
|
25
|
-
});
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
- `inputs` doubles as both the JSON-schema-like description sent to the model (translated per-provider by `src/core/tool-schema-translator.ts`) and the shape `execute` should expect on `inputs`.
|
|
29
|
-
- `stopIterationAfterUsingThisTool: true` ends the agent's run loop immediately after this tool fires, even if the model didn't naturally stop calling tools — useful for a "final answer" or "hand off" style tool.
|
|
30
|
-
- `execute`'s return value is normalized via `normalizeToolOutput()` into `{ output: {...} }` — return a plain object (or anything else) and it becomes `output` as-is, same convention as always.
|
|
31
|
-
- `envID` identifies which "environment" (in-process client id, IPC/WS session) the call came from — most tools ignore it unless they need per-environment isolated state (see `MCPStorage`/`MCPFSStorage` in [MCP Architecture](./mcp-architecture.md)).
|
|
32
|
-
- `toolCallId` is this specific call's id, needed only by a tool that calls `mcp.executeProvider(...)` (see below) — everything else can ignore it.
|
|
33
|
-
|
|
34
|
-
### `mcp.executeProvider(...)` — calling a provider from inside a tool
|
|
35
|
-
|
|
36
|
-
`MCP` (what `execute`'s 4th argument gives you, same as it always has) has one method beyond `getStorage()`/`getRNG()`:
|
|
37
|
-
|
|
38
|
-
```ts
|
|
39
|
-
abstract class MCP {
|
|
40
|
-
getStorage(): MCPStorage;
|
|
41
|
-
getRNG(): MCPRNG;
|
|
42
|
-
executeProvider(toolCallId: string, type: ProviderType, input: Record<string, any>): Promise<{ output: Record<string, any> }>;
|
|
43
|
-
}
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
`type` picks a role (see [Provider roles](./providers.md#provider-roles)); `input` must be `Message`-shaped — `{ content: string }` for plain text, or `{ parts: MessageContentPart[] }` when real multimodal content (an image, say) needs to reach the provider. `BaseAgent#executeProvider` spreads `input` straight onto the outgoing `role: "user"` message (no `safetyPolicies` system message here, unlike the main run loop — see [Guardrail system prompt](./agents.md#guardrail-system-prompt)) and stays completely type-agnostic itself — it never branches on `type`, so a role that needs `parts` (`image-describer`) and one that only needs `content` (a plain text-generation role) go through the exact same code path. Shaping `input` correctly is the calling tool's job: **use `parts`, not a `data:` URI folded into `content`, for images/video** — every built-in provider (Anthropic/OpenAI/DeepSeek/Ollama) only builds a real multimodal content block from `Message.parts`; a base64 string inside `content` is sent to the model as literal text, not an image. This works identically no matter where the tool is registered — directly on an `MCPClient`, or on a sandboxed/remote `MCPServer` (see [MCP Architecture](./mcp-architecture.md#custom-mcp-subclasses)) — because the actual provider call always happens on the trusted side (wherever `BaseAgent` lives): a client-registered tool reaches it in-process, a server-registered one has the request proxied there over the existing connection and back. No provider instance, or the credentials it holds, is ever visible to the tool — only this request/response.
|
|
47
|
-
|
|
48
|
-
**Off by default.** `executeProvider` throws immediately unless the owning `BaseAgent` was constructed with `features: { executeProviderFromMCPTool: true }` (see [`executeProvider` feature flag](./agents.md#executeprovider-feature-flag)) — a tool reaching a provider directly, with no guardrail prompt ahead of it, is a bigger trust surface than one that only returns data to the model, so it needs an explicit opt-in from whoever builds the agent.
|
|
49
|
-
|
|
50
|
-
`read-image`/`browser-screenshot` (below) are the reference example — the instruction as a `text` part, the base64 image as an `image` part:
|
|
51
|
-
|
|
52
|
-
```ts
|
|
53
|
-
const { output } = await mcp.executeProvider(toolCallId, "image-describer", {
|
|
54
|
-
parts: [
|
|
55
|
-
{ type: "text", text: instruction },
|
|
56
|
-
{ type: "image", image, mimeType },
|
|
57
|
-
],
|
|
58
|
-
});
|
|
59
|
-
return { description: output.content }; // output.content: string
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
If `executeProvider` rejects (no provider configured for that role, etc.), just let it throw — `BaseAgent`'s existing `execute()` error handling turns it into a normal `Error: ...` tool result, no special handling needed.
|
|
63
|
-
|
|
64
|
-
### Usage is never something a tool reports itself
|
|
65
|
-
|
|
66
|
-
There's no `usage` field on what `execute` returns. Every `executeProvider` call is recorded by `BaseAgent` the instant the real provider call resolves — keyed by `toolCallId`, moved onto the tool's result `Message.usage` only after `execute()` returns (see [Token accounting](./agents.md#token-accounting)) — specifically so a compromised or rewritten tool can't just under-report what it spent; it never holds that number to begin with.
|
|
67
|
-
|
|
68
|
-
Tools are registered on an `MCPServer` and invoked through an `MCPClient`; `SimpleAgent` does this wiring for you from a flat `tools` array.
|
|
69
|
-
|
|
70
|
-
One tool schema the model sees isn't an `MCPTool` at all: `BaseAgent` always appends a built-in `compact_memory` tool to the schema list, handled internally rather than routed through the `MCPClient`. See [Memory compaction](./agents.md#memory-compaction).
|
|
71
|
-
|
|
72
|
-
## Built-in tool catalog
|
|
73
|
-
|
|
74
|
-
Import a whole domain's tools at once (e.g. `FsTools()`), or import individual tools by name.
|
|
75
|
-
|
|
76
|
-
### Filesystem — `FsTools()`
|
|
77
|
-
|
|
78
|
-
> ⚠️ `FsWriteFileTool` and `FsDeleteTool` can permanently overwrite, delete, or corrupt existing files — no undo. Prefer routing filesystem access through `MCPComputer`'s sandbox (see [MCP Architecture](./mcp-architecture.md#mcpcomputer-sandboxed-execution)) to protect the host system, and/or gate these tools behind an `MCPExecutionPolicy` (see [`MCPExecutionPolicy`](./mcp-architecture.md#mcpexecutionpolicy-gating-tool-calls)) — e.g. denying `fs-write-file`/`fs-delete` outside an allowlisted directory, or requiring per-call confirmation.
|
|
79
|
-
|
|
80
|
-
| Tool | Purpose |
|
|
81
|
-
|---|---|
|
|
82
|
-
| `FsReadFileTool` | Read a text file, paging through large files by line. |
|
|
83
|
-
| `FsWriteFileTool` | Write/overwrite a file's full content (creates parent dirs as needed). ⚠️ No undo. |
|
|
84
|
-
| `FsEditFileTool` | Replace a specific line range in an existing file without rewriting the whole thing. |
|
|
85
|
-
| `FsListDirTool` | List a directory's entries, paged by index for large directories. |
|
|
86
|
-
| `FsCreateDirTool` | Create a directory, including missing parents. |
|
|
87
|
-
| `FsDeleteTool` | Permanently delete a file or directory (recursive optional). ⚠️ No undo. |
|
|
88
|
-
| `FsMoveTool` | Move or rename a file or directory. |
|
|
89
|
-
|
|
90
|
-
`FsReadFileTool` and `FsEditFileTool` both use **1-indexed** line numbers (line 1 is the first line of the file) for their `offsetLine` input — matching the convention most models already default to (`cat -n`, most editors). This is deliberate: a line number reported by `fs-read-file`'s `startLine`/`endLine` can be passed straight into `fs-edit-file`'s `offsetLine` without an off-by-one conversion. `limitLine` on both is a plain count, not a line number, so it isn't affected by the indexing.
|
|
91
|
-
| `FsStatTool` | Check whether a path exists and get its metadata (type, size, modified time). |
|
|
92
|
-
|
|
93
|
-
### Bash / processes — `BashTools()`
|
|
94
|
-
|
|
95
|
-
> ⚠️ Shell commands can permanently delete files, corrupt data, modify system settings, or execute harmful operations — no undo. Same sandboxing recommendation as above, and the same `MCPExecutionPolicy` option — e.g. denying `bash-run` calls whose command matches a deny-list, or routing them through a human-confirmation policy.
|
|
96
|
-
|
|
97
|
-
| Tool | Purpose |
|
|
98
|
-
|---|---|
|
|
99
|
-
| `BashRunTool` | Launch a shell command as a background process; returns immediately if it's still running after `waitMs` (e.g. a dev server). |
|
|
100
|
-
| `BashWaitTool` | Wait again on a previously started process and get its latest status/output. |
|
|
101
|
-
| `BashLogsTool` | Read a process's combined stdout/stderr, paged by line. |
|
|
102
|
-
| `BashListTool` | List every process launched so far with its status. |
|
|
103
|
-
| `BashWriteInputTool` | Send text to a running process's stdin (answer an interactive prompt like `(y/n)`). |
|
|
104
|
-
| `BashTerminateTool` | Terminate a running process. |
|
|
105
|
-
|
|
106
|
-
### Browser — `BrowserTools()`
|
|
107
|
-
|
|
108
|
-
Drives a real headless browser session.
|
|
109
|
-
|
|
110
|
-
| Tool | Purpose |
|
|
111
|
-
|---|---|
|
|
112
|
-
| `BrowserCreateSessionTool` | Open a new headless browser session at a URL, returns its `sessionId`. |
|
|
113
|
-
| `BrowserRemoveSessionTool` | Close and remove a browser session. |
|
|
114
|
-
| `BrowserGetSessionsTool` | List all currently open session ids. |
|
|
115
|
-
| `BrowserNavigateTool` | Navigate an existing session to a new URL. |
|
|
116
|
-
| `BrowserReadTool` | Read the page as a text outline (headings, tables, links, forms), assigning ref ids to clickable/fillable elements. |
|
|
117
|
-
| `BrowserClickTool` | Click a `[CLICKABLE]` element by ref id. |
|
|
118
|
-
| `BrowserFillTool` | Type into a `[FILLABLE]` element by ref id; can submit via Enter if the field's form has no visible submit button. |
|
|
119
|
-
| `BrowserSubmitFormTool` | Submit a `[FORM]` ref directly — for forms with no visible submit button. |
|
|
120
|
-
| `BrowserScrollInfoTool` | Get total scrollable length and current scroll position. |
|
|
121
|
-
| `BrowserScrollTool` | Scroll to a given vertical pixel position. |
|
|
122
|
-
| `BrowserConsoleTool` | Read captured browser console log messages. |
|
|
123
|
-
| `BrowserNetworkTool` | Read captured network request/response activity. |
|
|
124
|
-
| `BrowserNetworkStatusTool` | Check whether the page currently has in-flight network activity. |
|
|
125
|
-
| `BrowserInjectTool` | Evaluate arbitrary JS in the page and return the result. |
|
|
126
|
-
| `BrowserScreenshotTool` | Capture a screenshot and return a text description of it (via an `image-describer` provider — see [Provider roles](./providers.md#provider-roles)). |
|
|
127
|
-
|
|
128
|
-
### Todo lists — `TodoTools()`
|
|
129
|
-
|
|
130
|
-
Backs the `PlannerSkill` (see [Skills](./skills.md)), but usable standalone.
|
|
131
|
-
|
|
132
|
-
| Tool | Purpose |
|
|
133
|
-
|---|---|
|
|
134
|
-
| `TodoCreateListTool` | Create a new todo list, returns its `todoListId`. |
|
|
135
|
-
| `TodoRemoveListTool` | Remove one or more todo lists (and their tasks). |
|
|
136
|
-
| `TodoGetListsTool` | Get all existing todo list ids. |
|
|
137
|
-
| `TodoGetListTool` | Get all tasks belonging to a list. |
|
|
138
|
-
| `TodoCreateTaskTool` | Create one or more tasks inside a list. |
|
|
139
|
-
| `TodoRemoveTaskTool` | Remove one or more tasks by id. |
|
|
140
|
-
| `TodoCheckTaskTool` | Set the checked/unchecked state of one or more tasks. |
|
|
141
|
-
|
|
142
|
-
### Present / deliverables — `PresentTools()`
|
|
143
|
-
|
|
144
|
-
| Tool | Purpose |
|
|
145
|
-
|---|---|
|
|
146
|
-
| `PresentAddTool` | Present a file to the user by copying it into the present folder (zip folders first — this only accepts single files). |
|
|
147
|
-
| `PresentClearTool` | Clear out every file currently presented. |
|
|
148
|
-
| `PresentGetListTool` | Get the list of files currently presented. |
|
|
149
|
-
|
|
150
|
-
### Question / answer — `QuestionAnswerTools()`
|
|
151
|
-
|
|
152
|
-
| Tool | Purpose |
|
|
153
|
-
|---|---|
|
|
154
|
-
| `QuestionAnswerTool` | Ask the human operator a clarifying question and wait for their answer. |
|
|
155
|
-
|
|
156
|
-
### Utility — `UtilTools()`
|
|
157
|
-
|
|
158
|
-
| Tool | Purpose |
|
|
159
|
-
|---|---|
|
|
160
|
-
| `GetCurrentTimeTool` | Get the current date/time (ISO string, unix timestamp, timezone). |
|
|
161
|
-
| `DelayTool` | Wait a given number of milliseconds (max 60000ms) before continuing. |
|
|
162
|
-
| `ReadImageTool` | Read an image file off disk and return a text description of it — same handling as `BrowserScreenshotTool`. |
|
|
163
|
-
|
|
164
|
-
###
|
|
165
|
-
|
|
166
|
-
**
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
|
171
|
-
|
|
172
|
-
| `agent-
|
|
173
|
-
| `agent-
|
|
174
|
-
| `agent-prompt` |
|
|
175
|
-
|
|
176
|
-
`
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
-
|
|
1
|
+
# Tools
|
|
2
|
+
|
|
3
|
+
## The `MCPTool` shape
|
|
4
|
+
|
|
5
|
+
Every tool — built-in or custom — is an `MCPTool` instance (`src/core/mcp.ts`):
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
new MCPTool({
|
|
9
|
+
name: string;
|
|
10
|
+
description: string;
|
|
11
|
+
inputs: {
|
|
12
|
+
name: string;
|
|
13
|
+
type: "number" | "string" | "boolean" | "object" | "array";
|
|
14
|
+
description: string;
|
|
15
|
+
required?: boolean;
|
|
16
|
+
default?: any;
|
|
17
|
+
}[];
|
|
18
|
+
stopIterationAfterUsingThisTool?: boolean; // default false
|
|
19
|
+
execute: (
|
|
20
|
+
envID: string,
|
|
21
|
+
inputs: Record<string, any>,
|
|
22
|
+
toolCallId?: string,
|
|
23
|
+
mcp?: MCP
|
|
24
|
+
) => Promise<any>;
|
|
25
|
+
});
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
- `inputs` doubles as both the JSON-schema-like description sent to the model (translated per-provider by `src/core/tool-schema-translator.ts`) and the shape `execute` should expect on `inputs`.
|
|
29
|
+
- `stopIterationAfterUsingThisTool: true` ends the agent's run loop immediately after this tool fires, even if the model didn't naturally stop calling tools — useful for a "final answer" or "hand off" style tool.
|
|
30
|
+
- `execute`'s return value is normalized via `normalizeToolOutput()` into `{ output: {...} }` — return a plain object (or anything else) and it becomes `output` as-is, same convention as always.
|
|
31
|
+
- `envID` identifies which "environment" (in-process client id, IPC/WS session) the call came from — most tools ignore it unless they need per-environment isolated state (see `MCPStorage`/`MCPFSStorage` in [MCP Architecture](./mcp-architecture.md)).
|
|
32
|
+
- `toolCallId` is this specific call's id, needed only by a tool that calls `mcp.executeProvider(...)` (see below) — everything else can ignore it.
|
|
33
|
+
|
|
34
|
+
### `mcp.executeProvider(...)` — calling a provider from inside a tool
|
|
35
|
+
|
|
36
|
+
`MCP` (what `execute`'s 4th argument gives you, same as it always has) has one method beyond `getStorage()`/`getRNG()`:
|
|
37
|
+
|
|
38
|
+
```ts
|
|
39
|
+
abstract class MCP {
|
|
40
|
+
getStorage(): MCPStorage;
|
|
41
|
+
getRNG(): MCPRNG;
|
|
42
|
+
executeProvider(toolCallId: string, type: ProviderType, input: Record<string, any>): Promise<{ output: Record<string, any> }>;
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
`type` picks a role (see [Provider roles](./providers.md#provider-roles)); `input` must be `Message`-shaped — `{ content: string }` for plain text, or `{ parts: MessageContentPart[] }` when real multimodal content (an image, say) needs to reach the provider. `BaseAgent#executeProvider` spreads `input` straight onto the outgoing `role: "user"` message (no `safetyPolicies` system message here, unlike the main run loop — see [Guardrail system prompt](./agents.md#guardrail-system-prompt)) and stays completely type-agnostic itself — it never branches on `type`, so a role that needs `parts` (`image-describer`) and one that only needs `content` (a plain text-generation role) go through the exact same code path. Shaping `input` correctly is the calling tool's job: **use `parts`, not a `data:` URI folded into `content`, for images/video** — every built-in provider (Anthropic/OpenAI/DeepSeek/Ollama) only builds a real multimodal content block from `Message.parts`; a base64 string inside `content` is sent to the model as literal text, not an image. This works identically no matter where the tool is registered — directly on an `MCPClient`, or on a sandboxed/remote `MCPServer` (see [MCP Architecture](./mcp-architecture.md#custom-mcp-subclasses)) — because the actual provider call always happens on the trusted side (wherever `BaseAgent` lives): a client-registered tool reaches it in-process, a server-registered one has the request proxied there over the existing connection and back. No provider instance, or the credentials it holds, is ever visible to the tool — only this request/response.
|
|
47
|
+
|
|
48
|
+
**Off by default.** `executeProvider` throws immediately unless the owning `BaseAgent` was constructed with `features: { executeProviderFromMCPTool: true }` (see [`executeProvider` feature flag](./agents.md#executeprovider-feature-flag)) — a tool reaching a provider directly, with no guardrail prompt ahead of it, is a bigger trust surface than one that only returns data to the model, so it needs an explicit opt-in from whoever builds the agent. In a swarm the opt-in is the swarm's, not each agent's — see [Swarm](./swarm.md#providers-a-tool-reaches-for).
|
|
49
|
+
|
|
50
|
+
`read-image`/`browser-screenshot` (below) are the reference example — the instruction as a `text` part, the base64 image as an `image` part:
|
|
51
|
+
|
|
52
|
+
```ts
|
|
53
|
+
const { output } = await mcp.executeProvider(toolCallId, "image-describer", {
|
|
54
|
+
parts: [
|
|
55
|
+
{ type: "text", text: instruction },
|
|
56
|
+
{ type: "image", image, mimeType },
|
|
57
|
+
],
|
|
58
|
+
});
|
|
59
|
+
return { description: output.content }; // output.content: string
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
If `executeProvider` rejects (no provider configured for that role, etc.), just let it throw — `BaseAgent`'s existing `execute()` error handling turns it into a normal `Error: ...` tool result, no special handling needed.
|
|
63
|
+
|
|
64
|
+
### Usage is never something a tool reports itself
|
|
65
|
+
|
|
66
|
+
There's no `usage` field on what `execute` returns. Every `executeProvider` call is recorded by `BaseAgent` the instant the real provider call resolves — keyed by `toolCallId`, moved onto the tool's result `Message.usage` only after `execute()` returns (see [Token accounting](./agents.md#token-accounting)) — specifically so a compromised or rewritten tool can't just under-report what it spent; it never holds that number to begin with. (In a swarm, `SwarmBase` answers the call but records it the same way, back onto the calling agent's tool-result message — see [Providers a tool reaches for](./swarm.md#providers-a-tool-reaches-for).)
|
|
67
|
+
|
|
68
|
+
Tools are registered on an `MCPServer` and invoked through an `MCPClient`; `SimpleAgent` does this wiring for you from a flat `tools` array.
|
|
69
|
+
|
|
70
|
+
One tool schema the model sees isn't an `MCPTool` at all: `BaseAgent` always appends a built-in `compact_memory` tool to the schema list, handled internally rather than routed through the `MCPClient`. See [Memory compaction](./agents.md#memory-compaction).
|
|
71
|
+
|
|
72
|
+
## Built-in tool catalog
|
|
73
|
+
|
|
74
|
+
Import a whole domain's tools at once (e.g. `FsTools()`), or import individual tools by name.
|
|
75
|
+
|
|
76
|
+
### Filesystem — `FsTools()`
|
|
77
|
+
|
|
78
|
+
> ⚠️ `FsWriteFileTool` and `FsDeleteTool` can permanently overwrite, delete, or corrupt existing files — no undo. Prefer routing filesystem access through `MCPComputer`'s sandbox (see [MCP Architecture](./mcp-architecture.md#mcpcomputer-sandboxed-execution)) to protect the host system, and/or gate these tools behind an `MCPExecutionPolicy` (see [`MCPExecutionPolicy`](./mcp-architecture.md#mcpexecutionpolicy-gating-tool-calls)) — e.g. denying `fs-write-file`/`fs-delete` outside an allowlisted directory, or requiring per-call confirmation.
|
|
79
|
+
|
|
80
|
+
| Tool | Purpose |
|
|
81
|
+
|---|---|
|
|
82
|
+
| `FsReadFileTool` | Read a text file, paging through large files by line. |
|
|
83
|
+
| `FsWriteFileTool` | Write/overwrite a file's full content (creates parent dirs as needed). ⚠️ No undo. |
|
|
84
|
+
| `FsEditFileTool` | Replace a specific line range in an existing file without rewriting the whole thing. |
|
|
85
|
+
| `FsListDirTool` | List a directory's entries, paged by index for large directories. |
|
|
86
|
+
| `FsCreateDirTool` | Create a directory, including missing parents. |
|
|
87
|
+
| `FsDeleteTool` | Permanently delete a file or directory (recursive optional). ⚠️ No undo. |
|
|
88
|
+
| `FsMoveTool` | Move or rename a file or directory. |
|
|
89
|
+
|
|
90
|
+
`FsReadFileTool` and `FsEditFileTool` both use **1-indexed** line numbers (line 1 is the first line of the file) for their `offsetLine` input — matching the convention most models already default to (`cat -n`, most editors). This is deliberate: a line number reported by `fs-read-file`'s `startLine`/`endLine` can be passed straight into `fs-edit-file`'s `offsetLine` without an off-by-one conversion. `limitLine` on both is a plain count, not a line number, so it isn't affected by the indexing.
|
|
91
|
+
| `FsStatTool` | Check whether a path exists and get its metadata (type, size, modified time). |
|
|
92
|
+
|
|
93
|
+
### Bash / processes — `BashTools()`
|
|
94
|
+
|
|
95
|
+
> ⚠️ Shell commands can permanently delete files, corrupt data, modify system settings, or execute harmful operations — no undo. Same sandboxing recommendation as above, and the same `MCPExecutionPolicy` option — e.g. denying `bash-run` calls whose command matches a deny-list, or routing them through a human-confirmation policy.
|
|
96
|
+
|
|
97
|
+
| Tool | Purpose |
|
|
98
|
+
|---|---|
|
|
99
|
+
| `BashRunTool` | Launch a shell command as a background process; returns immediately if it's still running after `waitMs` (e.g. a dev server). |
|
|
100
|
+
| `BashWaitTool` | Wait again on a previously started process and get its latest status/output. |
|
|
101
|
+
| `BashLogsTool` | Read a process's combined stdout/stderr, paged by line. |
|
|
102
|
+
| `BashListTool` | List every process launched so far with its status. |
|
|
103
|
+
| `BashWriteInputTool` | Send text to a running process's stdin (answer an interactive prompt like `(y/n)`). |
|
|
104
|
+
| `BashTerminateTool` | Terminate a running process. |
|
|
105
|
+
|
|
106
|
+
### Browser — `BrowserTools()`
|
|
107
|
+
|
|
108
|
+
Drives a real headless browser session.
|
|
109
|
+
|
|
110
|
+
| Tool | Purpose |
|
|
111
|
+
|---|---|
|
|
112
|
+
| `BrowserCreateSessionTool` | Open a new headless browser session at a URL, returns its `sessionId`. |
|
|
113
|
+
| `BrowserRemoveSessionTool` | Close and remove a browser session. |
|
|
114
|
+
| `BrowserGetSessionsTool` | List all currently open session ids. |
|
|
115
|
+
| `BrowserNavigateTool` | Navigate an existing session to a new URL. |
|
|
116
|
+
| `BrowserReadTool` | Read the page as a text outline (headings, tables, links, forms), assigning ref ids to clickable/fillable elements. |
|
|
117
|
+
| `BrowserClickTool` | Click a `[CLICKABLE]` element by ref id. |
|
|
118
|
+
| `BrowserFillTool` | Type into a `[FILLABLE]` element by ref id; can submit via Enter if the field's form has no visible submit button. |
|
|
119
|
+
| `BrowserSubmitFormTool` | Submit a `[FORM]` ref directly — for forms with no visible submit button. |
|
|
120
|
+
| `BrowserScrollInfoTool` | Get total scrollable length and current scroll position. |
|
|
121
|
+
| `BrowserScrollTool` | Scroll to a given vertical pixel position. |
|
|
122
|
+
| `BrowserConsoleTool` | Read captured browser console log messages. |
|
|
123
|
+
| `BrowserNetworkTool` | Read captured network request/response activity. |
|
|
124
|
+
| `BrowserNetworkStatusTool` | Check whether the page currently has in-flight network activity. |
|
|
125
|
+
| `BrowserInjectTool` | Evaluate arbitrary JS in the page and return the result. |
|
|
126
|
+
| `BrowserScreenshotTool` | Capture a screenshot and return a text description of it (via an `image-describer` provider — see [Provider roles](./providers.md#provider-roles)). |
|
|
127
|
+
|
|
128
|
+
### Todo lists — `TodoTools()`
|
|
129
|
+
|
|
130
|
+
Backs the `PlannerSkill` (see [Skills](./skills.md)), but usable standalone.
|
|
131
|
+
|
|
132
|
+
| Tool | Purpose |
|
|
133
|
+
|---|---|
|
|
134
|
+
| `TodoCreateListTool` | Create a new todo list, returns its `todoListId`. |
|
|
135
|
+
| `TodoRemoveListTool` | Remove one or more todo lists (and their tasks). |
|
|
136
|
+
| `TodoGetListsTool` | Get all existing todo list ids. |
|
|
137
|
+
| `TodoGetListTool` | Get all tasks belonging to a list. |
|
|
138
|
+
| `TodoCreateTaskTool` | Create one or more tasks inside a list. |
|
|
139
|
+
| `TodoRemoveTaskTool` | Remove one or more tasks by id. |
|
|
140
|
+
| `TodoCheckTaskTool` | Set the checked/unchecked state of one or more tasks. |
|
|
141
|
+
|
|
142
|
+
### Present / deliverables — `PresentTools()`
|
|
143
|
+
|
|
144
|
+
| Tool | Purpose |
|
|
145
|
+
|---|---|
|
|
146
|
+
| `PresentAddTool` | Present a file to the user by copying it into the present folder (zip folders first — this only accepts single files). |
|
|
147
|
+
| `PresentClearTool` | Clear out every file currently presented. |
|
|
148
|
+
| `PresentGetListTool` | Get the list of files currently presented. |
|
|
149
|
+
|
|
150
|
+
### Question / answer — `QuestionAnswerTools()`
|
|
151
|
+
|
|
152
|
+
| Tool | Purpose |
|
|
153
|
+
|---|---|
|
|
154
|
+
| `QuestionAnswerTool` | Ask the human operator a clarifying question and wait for their answer. |
|
|
155
|
+
|
|
156
|
+
### Utility — `UtilTools()`
|
|
157
|
+
|
|
158
|
+
| Tool | Purpose |
|
|
159
|
+
|---|---|
|
|
160
|
+
| `GetCurrentTimeTool` | Get the current date/time (ISO string, unix timestamp, timezone). |
|
|
161
|
+
| `DelayTool` | Wait a given number of milliseconds (max 60000ms) before continuing. |
|
|
162
|
+
| `ReadImageTool` | Read an image file off disk and return a text description of it — same handling as `BrowserScreenshotTool`. |
|
|
163
|
+
|
|
164
|
+
### Swarm — `getAgentTools(options?)`
|
|
165
|
+
|
|
166
|
+
Unlike every other domain above, this one doesn't return an `MCPTool[]`. It returns a **handle** whose `.tools` is the array, because the same object also has to be handed to `SwarmBase` — the tools and the swarm share the state minted when the handle is built (the hire pool, and which swarm they drive). Full walkthrough in [Swarm](./swarm.md).
|
|
167
|
+
|
|
168
|
+
| Tool | Purpose |
|
|
169
|
+
|---|---|
|
|
170
|
+
| `agent-types` | List the kinds of agent this swarm can hire — description, ratings, how many are working, slots left. |
|
|
171
|
+
| `agent-hire` | Spawn an agent of a type, optionally into a group and with a standing briefing. The caller becomes its parent. |
|
|
172
|
+
| `agent-fire` | Release one of your own hires and free its slot. |
|
|
173
|
+
| `agent-active` | List every hired agent — id, type, groups, parent, `busy`, `awaitingReport`. The last two together separate "working" from "paused mid-task" from "idle" — see [Swarm](./swarm.md#telling-a-paused-agent-from-a-dead-one). |
|
|
174
|
+
| `agent-prompt` | Hand a task to one of your hires; returns immediately, the answer comes back later as a report. |
|
|
175
|
+
| `agent-report-parent` | Send a result to the agent that hired you, ending your turn. |
|
|
176
|
+
| `agent-report-group` | Send a message to your group's other members; your parent never sees it, and your turn continues. |
|
|
177
|
+
|
|
178
|
+
Who can do what is decided by which of these each agent's `allowedTools` includes — hiring tools for a planner, reporting tools for a worker — not by building separate tool sets. `{ maxHired }` caps hires across the whole swarm as one shared pool, and is woven into `agent-hire`'s own description so the model sees the constraint.
|
|
179
|
+
|
|
180
|
+
## Writing a custom tool
|
|
181
|
+
|
|
182
|
+
```ts
|
|
183
|
+
import { MCPTool } from "orbitx";
|
|
184
|
+
|
|
185
|
+
export const SumTool = () => new MCPTool({
|
|
186
|
+
name: "math-sum",
|
|
187
|
+
description: "get two numbers and sum them",
|
|
188
|
+
inputs: [
|
|
189
|
+
{ name: "first", type: "number", description: "first number", required: true },
|
|
190
|
+
{ name: "second", type: "number", description: "second number", required: true },
|
|
191
|
+
],
|
|
192
|
+
execute: async (_envID: string, inputs: Record<string, any>) => {
|
|
193
|
+
const { first, second } = inputs;
|
|
194
|
+
if (typeof first !== "number") throw new Error("first must be a number");
|
|
195
|
+
if (typeof second !== "number") throw new Error("second must be a number");
|
|
196
|
+
return { output: first + second };
|
|
197
|
+
},
|
|
198
|
+
});
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Use it exactly like a built-in tool:
|
|
202
|
+
|
|
203
|
+
```ts
|
|
204
|
+
const agent = new SimpleAgent({
|
|
205
|
+
aiProvider: provider,
|
|
206
|
+
instruction: "You are a helpful assistant.",
|
|
207
|
+
tools: [SumTool()],
|
|
208
|
+
});
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Conventions worth following, based on the built-in tools:
|
|
212
|
+
- Export a **factory function** (`SumTool()`), not the `MCPTool` instance itself — this keeps each agent's tool list made of fresh instances.
|
|
213
|
+
- Throw inside `execute` for invalid input rather than returning an error object — thrown errors are caught by `BaseAgent` and turned into a `Error: ...` result the model sees, which is usually what you want.
|
|
214
|
+
- Keep `description` and each input's `description` written for the model, not for a human reader of your source — they go straight into the tool schema.
|