Tools
AgentFlow supports remote tools — functions that are defined and executed in the browser (or any client environment) while the server-side agent graph coordinates the calls. The server asks the client to run a tool by embedding RemoteToolCallBlock entries in its response. The client detects these, executes the corresponding handler, and sends the results back.
Remote tools are primarily designed for operations that only make sense on the client: accessing the user's camera, reading local files, interacting with the DOM, calling a browser-only API, or running lightweight compute without a round-trip to a separate backend.
For operations that can run on the server (LLM tool calls, web search, database queries), use the Python graph's built-in toolset instead.
Source: src/tools.ts, src/endpoints/setupGraph.ts
Import
import {
AgentFlowClient,
ToolRegistration,
ToolDefinition,
ToolParameter,
Tool,
ToolExecutor,
} from '@10xscale/agentflow-client';
Workflow
- Define tool handlers in the client.
- Call
client.registerTool()for each one before the firstinvoke()orstream()call. - Call
client.setup()to send all tool definitions to the server. - Call
client.invoke()orclient.stream()— tool execution is handled automatically inside the loop.
registerTool(registration)
Register a tool handler with the client. This stores the handler locally; it does not yet inform the server.
client.registerTool({
node: 'tools', // The graph node that can call this tool
name: 'get_weather',
description: 'Get the current weather for a city',
parameters: {
type: 'object',
properties: {
city: {
type: 'string',
description: 'Name of the city',
},
},
required: ['city'],
},
handler: async ({ city }) => {
// Execute locally — could call a browser API, local storage, etc.
const response = await fetch(`https://wttr.in/${city}?format=j1`);
const data = await response.json();
return { temperature: data.current_condition[0].temp_C };
},
});
ToolRegistration
interface ToolRegistration {
node: string; // Name of the graph node that owns this tool
name: string; // Tool name — must match what the graph calls
description?: string; // Human-readable description (sent to the server)
parameters?: ToolParameter; // JSON Schema for the tool's input arguments
handler: ToolHandler; // async function that executes the tool
}
ToolParameter
interface ToolParameter {
type: string; // Always 'object'
properties: Record<string, any>; // JSON Schema properties
required: string[]; // List of required property names
}
ToolHandler
type ToolHandler = (args: any) => Promise<any>;
The args object matches the shape declared in parameters.properties. The return value can be any JSON-serialisable value. It is wrapped in a ToolResultBlock and sent back to the server.
setup()
Send all registered tool definitions to the server so the graph knows which remote tools are available and what parameters they accept.
await client.setup();
setup() posts to /v1/graph/setup with the list of RemoteTool objects derived from your registrations. You must call this before the first invoke() or stream() call that uses tools. Calling it again after adding more tools is safe — the server replaces the previous registration.
SetupGraphResponse
interface SetupGraphResponse {
data: {
success: boolean;
message: string;
registered_tools?: number; // Number of tools registered on the server
};
metadata: ResponseMetadata;
}
RemoteTool (internal)
This is the wire format sent to the server. You do not construct this manually — client.setup() creates it from your ToolRegistration objects.
interface RemoteTool {
node_name: string;
name: string;
description: string;
parameters: Record<string, any>;
}