Tools
Tools extend what agents can do. In Octavus, tools can execute either on your server or on the client side.
Server Tools vs Client Tools
| Location | Use Case | Registration |
|---|---|---|
| Server | Database queries, API calls, sensitive operations | Register handler in attach() |
| Inline MCP | Group an integration's tools (GitHub, Salesforce) | createInlineMcpServer() |
| Computer | Browser, filesystem, shell, external services | session.setDynamicTools() |
| Client | Browser APIs, interactive UIs, confirmations | No server handler (forwarded to client) |
When the Server SDK encounters a tool call:
- Handler exists (server, inline MCP, or dynamic) → Execute on server, continue automatically
- No handler → Forward to client via
client-tool-requestevent
Inline MCP tools and dynamic tools registered via session.setDynamicTools() (e.g., from @octavus/computer) work identically to manual handlers from the platform's perspective. See Inline MCP Servers for namespaced consumer-defined tool groups, and Computer for device-side MCPs.
For client-side tool handling, see Client Tools.
Why Server Tools
Server-side tools give you full control:
- ✅ Full data access - Query your database directly
- ✅ Your authentication - Use your existing auth context
- ✅ No data exposure - Sensitive data never leaves your infrastructure
- ✅ Custom logic - Any complexity you need
Defining Tool Handlers
Tool handlers are async functions that receive arguments and return results:
Using Tools in Sessions
Pass tool handlers when attaching to a session:
Tool Handler Signature
Arguments
Arguments are passed as a Record<string, unknown>. Type-check as needed:
Return Values
Return any JSON-serializable value. The result is:
- Sent back to the LLM as context
- Stored in session state
- Optionally stored in a variable for protocol use
Error Handling
Throw errors for failures. They're captured and sent to the LLM:
The LLM receives the error message and can respond appropriately (e.g., "I couldn't find that account").
Tool Execution Flow
When the LLM calls a tool:
Accessing Request Context
For request-specific data (auth, headers), create handlers dynamically: