Creating Tools

Extend Kibo with your own custom tools. Tools are Python functions decorated with @needle.tool.

Architecture Overview

agent/tools/ ├── __init__.py # Registry - imports all tools ├── system.py # Notifications, battery, clipboard ├── hardware.py # Device info, screenshots, power ├── communication.py # Clipboard operations ├── media.py # Camera, TTS, audio recording ├── network.py # WiFi, internet, downloads ├── apps.py # App launching, file listing ├── sysadmin.py # Processes, files, packages └── advanced.py # Remote terminal, media streaming

Tool Anatomy

Every tool follows the same pattern:

import needle from agent.runner import some_function @needle.tool def my_tool(param1: str, param2: int = 10) -> str: """Description of what the tool does. This docstring is used by the AI agent to understand when and how to use this tool. """ print(f"[Tool] my_tool('{param1}', {param2})") # Call runner function for OS-specific logic result = some_function(param1, param2) return f"Result: {result}"

Key Rules

@needle.tool

Every tool must be decorated with this. It registers the function with the AI agent.

Docstring = Description

The AI uses your docstring to decide when to call the tool. Write clearly.

Type Hints

Required. The AI uses them to understand expected inputs.

Return Strings

All tools must return a string. The AI processes the result.

Print Logging

Use print(f"[Tool] ...") for debugging output.

Error Handling

Return error messages as strings. Don't raise exceptions.

Step-by-Step Guide

Step 1: Create the tool file

Create a new file in agent/tools/:

# agent/tools/calculator.py

Step 2: Implement the tool

import needle @needle.tool def calculate(expression: str) -> str: """Evaluate a mathematical expression. Examples: "2 + 2", "10 * 5", "100 / 7" """ print(f"[Tool] calculate('{expression}')") try: result = eval(expression, {"__builtins__": {}}, {}) return f"Result: {result}" except Exception as e: return f"Error: {e}"

Step 3: Register the tool

Add the import and append to ALL_TOOLS in agent/tools/__init__.py:

# agent/tools/__init__.py from agent.tools.calculator import calculate ALL_TOOLS = [ # ... existing tools ... calculate, ]

Step 4: Test it

Start Kibo and try your new tool:

./run.sh > calculate 2 + 2 Result: 4

Using Runner Functions

For OS-specific logic, delegate to runner modules. This keeps your tools cross-platform:

import needle from agent.runner import notify @needle.tool def remind_me(message: str, minutes: int = 5) -> str: """Set a reminder that shows a notification.""" print(f"[Tool] remind_me('{message}', {minutes})") # Implementation... return notify("Reminder", message)

Runner functions in agent/runner/ handle platform differences (Linux, macOS, Windows).

Real Examples from Kibo

show_toast
@needle.tool

Show a brief toast popup. Takes a message string.

take_screenshot_now
@needle.tool

Capture screen. Returns file path to the screenshot.

get_battery_status
@needle.tool

Check battery level. Returns percentage and charging status.

set_volume
@needle.tool

Set system volume. Takes an integer 0-100.

Tips

Keep it simple

Each tool should do one thing well. Break complex operations into multiple tools.

Use default parameters

Make common parameters required and optional ones have defaults. The AI handles this better.

Write clear docstrings

Include examples in the docstring. The AI uses them to understand usage patterns.

Test with both models

Try your tool with both Needle 2 and FunctionGemma to ensure compatibility.