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 return a string or object response.
Basic Implementation
Here’s a simple example of implementing a tool:
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!`;
    }
}
The @tool decorator defines the tool itself and accepts the following options:
@tool({
    name?: string;
    description?: string;
    cache?: boolean;
    enabled?: (agent: MagmaAgent) => boolean
})
- name: The name of the tool.
- description: A description of the tool.
- cache: Try to cache the tool if supported by the provider.
- enabled: Dynamically enable or disable the tool based on agent state. Disabled tools are not supplied to the provider. If omitted, the tool will always be enabled.
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- MagmaToolParamobjects which define the properties of the object.
Array-specific options:
- items: A- MagmaToolParamobject which defines the type of the items in the array.
You should get intellisense for what properties are available for a given parameter type.
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
- 
Return Values
- Tools can return a string or object
- Tools should return meaningful success/error messages
- Tool return values should be concise and informative
 
- 
Error Handling
- While you can use a normal return string for failed tools, it is best practice to throw an error. The error message will be passed to the agent and it will attempt to fix the issue.
 @tool({ description: "Process a transaction" })
async processTransaction(call: MagmaToolCall) {
    try {
        // Implementation
        return "Transaction processed successfully";
    } catch (error) {
        throw new Error(`Transaction failed: ${error.message}`);
    }
}
 
- 
Type Safety
- Use proper TypeScript types
- Avoid using anytype
- 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