Overview

Tools are the primary way to extend your Magma agent’s capabilities. They allow your agent to interact with external systems, process data, and perform specific tasks.

Tools are asynchronous methods that MUST return a string response.

Basic Implementation

Here’s a simple example of implementing a tool:

myAgent.ts
import { MagmaAgent } from "@pompeii-labs/magma";

export default class MyAgent extends MagmaAgent {

    // We can define a tool using the @tool decorator
    // We can define parameters for the tool using the @toolparam decorator
    @tool({ description: "Get the current weather for a city" })
    @toolparam({
        key: "city",
        type: "string",
        description: "Name of the city",
    })
    async getWeather(call: MagmaToolCall) {
        const { city } = call.fn_args;
        // Implementation here
        return `The weather in ${city} is sunny!`;
    }

}

Tool Decorators

@tool Decorator

The @tool decorator defines the tool itself and accepts the following options:

@tool({
    name?: string;
    description?: string;
})
  • name: The name of the tool.
  • description: A description of the tool.

@toolparam Decorator

The @toolparam decorator defines parameters for your tool:

@toolparam({
    key: string;
    type: string;
    description?: string;
    required?: boolean;
})
  • key: The name of the parameter.
  • type: The type of the parameter.
  • description: A description of the parameter.
  • required: Whether the parameter is required to run the tool. Defaults to false.

Primitive-specific options:

  • enum: Possible values for the parameter.

Object-specific options:

  • properties: An array of MagmaToolParam objects which define the properties of the object.

Array-specific options:

  • items: A MagmaToolParam object which defines the type of the items in the array.

You should get intellisense for what properties are available for a given parameter type.


Advanced Tool Parameters

Tools can accept complex parameter types:

@tool({ description: "Search database records" })
@toolparam({
    key: "filters",
    type: "object",
    properties: [
        { key: "date", type: "string" },
        { key: "category", type: "string", enum: ["A", "B", "C"] }
    ]
})
@toolparam({
    key: "limit",
    type: "number",
    description: "Maximum number of results",
    required: false
})
async searchDatabase(call: MagmaToolCall) {
    const { filters, limit } = call.fn_args;
    // Implementation here
    return "Search results: ...";
}

Best Practices

  1. Return Values

    • Tools must always return a string
    • Return meaningful success/error messages
    • Keep responses concise and informative
  2. Error Handling

    @tool({ description: "Process a transaction" })
    async processTransaction(call: MagmaToolCall) {
        try {
            // Implementation
            return "Transaction processed successfully";
        } catch (error) {
            throw new Error(`Transaction failed: ${error.message}`);
        }
    }
    
  3. Type Safety

    • Use proper TypeScript types
    • Avoid using any type
    • Validate input parameters

Common Use Cases

API Integration

@tool({ description: "Fetch user data from API" })
@toolparam({
    key: "userId",
    type: "string",
    description: "User's unique identifier"
})
async fetchUserData(call: MagmaToolCall) {
    const { userId } = call.fn_args;
    const response = await fetch(`https://api.example.com/users/${userId}`);
    const data = await response.json();
    return JSON.stringify(data);
}

File Operations

@tool({ description: "Read file contents" })
@toolparam({
    key: "path",
    type: "string",
    description: "Path to file"
})
async readFile(call: MagmaToolCall) {
    const { path } = call.fn_args;
    const content = await fs.readFile(path, 'utf-8');
    return content;
}

Remember that tool responses are used as context for the agent’s next action. Keep responses clear and structured to help the agent make better decisions.


For more examples and advanced usage, check out some of our Templates