Skip to content

Agent Tools

What is a Agent Tool?

In the Eko framework, Tools are the core capability of an agent, the component that truly executes the calls, and an agent must contain one or more tools to complete its work.

How to Custom Tools in Agent?

Each Tool needs to implement the following core elements:

  • name: Unique identifier for the Tool
  • description: Functional description of the Tool
  • parameters: Input parameter structure definition
  • execute: Specific execution logic

To create custom Tools in Eko agent, you need to follow these steps:

  1. Define input and output structures: Clearly specify the Tool’s input parameters and output results.
  2. Implement Tool interface: Inherit or implement the Tool interface and define related properties and methods.
  3. Handle parameters: Write implementation logic for specific functionality in the execute method.
interface Tool {
name: string; // tool name
description: string; // A functional description explaining the tool's purpose and usage scenarios
parameters: InputSchema; // A functional description explaining the tool's purpose and usage scenarios
execute: (args: Record<string, unknown>, agentContext: AgentContext, toolCall: LanguageModelV1ToolCallPart) => Promise<ToolResult>; // Execute function
}

Creating a Agent Tool

Let’s explain how to create a custom Tool through a simple example.

Suppose we want to create an email sending Tool:

import { AgentContext } from "@eko-ai/eko";
import { Tool, ToolResult, LanguageModelV1ToolCallPart } from "@eko-ai/eko/types";
class SendEmail implements Tool {
name: string;
description: string;
parameters: any;
constructor() {
this.name = "send_email";
this.description = "Send email to specified recipient";
this.parameters = {
type: "object",
properties: {
to: {
type: "string",
description: "Email address of the recipient",
},
subject: {
type: "string",
description: "Email subject",
},
content: {
type: "string",
description: "Email content",
},
},
required: ["to", "subject", "content"],
};
}
async execute(
args: Record<string, unknown>,
agentContext: AgentContext,
toolCall: LanguageModelV1ToolCallPart
): Promise<ToolResult> {
// Implement specific email sending logic
// This is just an example
let emailService: any;
const result = await emailService.send({
to: args.to,
subject: args.subject,
content: args.content,
});
return {
content: [
{ type: "text", text: JSON.stringify({ messageId: result.id }) },
],
};
}
}

Advanced Features

Session state (variable)

In the tool execute function, it supports reading or saving variable information across tools or across agents.

async execute(
args: Record<string, unknown>,
agentContext: AgentContext,
toolCall: LanguageModelV1ToolCallPart
): Promise<ToolResult> {
// Example: Reading and writing variables (effective within the current agent execution process during the current task, Cross-tool)
let id1 = agentContext.variables.get("id1");
if (!id1) {
agentContext.variables.set("id1", "xxxx");
}
// Example: Reading and writing variables (the lifecycle is effective during the current task's execution process, Cross-agent)
let id2 = agentContext.context.variables.get("id2");
if (!id2) {
agentContext.context.variables.set("id2", "xxxx");
}
return {
content: [
{ type: "text", text: "Successful" },
],
};
}

callback tool_running event

Supports callback events during tool invocation. For example, some tools take longer to execute and generate logs or streaming output data during execution that need to be exposed in real-time through callbacks, such as real-time logs generated by Python code execution tools.

async execute(
args: Record<string, unknown>,
agentContext: AgentContext,
toolCall: LanguageModelV1ToolCallPart
): Promise<ToolResult> {
// Real-time logs generated during the execution of the simulation tool
const logs = ["Simulation log1", "Simulation log2", "Simulation log3"];
// Callback function
const callback = agentContext.context.config.callback || {
onMessage: async (message: StreamCallbackMessage) => {},
};
// Streaming Message ID
const streamId = uuidv4();
for (let i = 0; i < logs.length; i++) {
let log = logs[i];
// Callback streaming tool_running message
await callback.onMessage({
taskId: agentContext.context.taskId,
agentName: agentContext.agent.Name,
nodeId: agentContext.agentChain.agent.id,
type: "tool_running",
toolName: toolCall.toolName,
toolId: toolCall.toolCallId,
text: log,
streamId: streamId,
streamDone: false,
});
}
// Final tool_running message
await callback.onMessage({
taskId: agentContext.context.taskId,
agentName: agentContext.agent.Name,
nodeId: agentContext.agentChain.agent.id,
type: "tool_running",
toolName: toolCall.toolName,
toolId: toolCall.toolCallId,
text: logs.join("\n"),
streamId: streamId,
streamDone: true,
});
return {
content: [{ type: "text", text: "Successful" }],
};
}

Specific hook descriptions please refer to: Hook system.