AgentsFlowCompiler-lib 0.1.0
Visual Agent Workflow Engine — run AI agent pipelines from YAML configuration
License: MIT
Requires Python: >=3.10
Keywords: agents, llm, workflow, pipeline, yaml, openai, anthropic, gemini

# 🔧 AgentsFlow Tools

## Overview

Tools give your agents the ability to perform actions — search the web, calculate math, call APIs, read files, and anything else you can write in Python.

There are two types of tools:

| Type | Where it lives | Who can use it | Config |
|------|---------------|----------------|--------|
| **Built-in** | `tools/{tool_name}/` | All agents | Just add the name to YAML |
| **Custom** | Agent's own directory | Only that agent | Full definition in YAML |

---

## Using Built-in Tools

### Available Built-in Tools

| Tool | Category | Description |
|------|----------|-------------|
| `calculator` | math | Safely evaluate math expressions (sqrt, log, sin, +, -, *, /, etc.) |
| `web_search` | search | Search the web (requires implementation — see below) |

### Adding a Built-in Tool to an Agent

In your agent's `config.yaml`, add a `tools` list:

```yaml
analyzer:
  agent_id: node_001
  model: gpt-4
  instruction_path: instruction.md
  tools:
    - name: calculator
      custom: false
```

That's it. The agent can now use the calculator.

### Multiple Built-in Tools

```yaml
analyzer:
  model: gpt-4
  instruction_path: instruction.md
  tools:
    - name: calculator
      custom: false
    - name: web_search
      custom: false
```

---

## Creating Custom Tools

Custom tools are tools you write yourself, specific to one agent.

### Step 1: Write the Python Function

Create a `.py` file in your agent's directory:

```
agents/
  analyzer/
    config.yaml
    instruction.md
    my_tools.py       ← your tool code
```

```python
# agents/analyzer/my_tools.py

def fetch_price(ticker: str) -> dict:
    """Fetch stock price for a given ticker symbol."""
    import requests
    resp = requests.get(f"https://api.example.com/price/{ticker}")
    data = resp.json()
    return {
        "ticker": ticker,
        "price": data["price"],
        "currency": "USD"
    }


def translate(text: str, target_lang: str = "en") -> str:
    """Translate text to target language."""
    # your translation logic here
    return translated_text
```

### Step 2: Define in YAML

```yaml
analyzer:
  model: gpt-4
  instruction_path: instruction.md
  tools:
    - name: stock_price
      custom: true
      description: "Fetch current stock price for a ticker symbol"
      category: finance
      path: my_tools.py
      function_name: fetch_price
      parameters:
        ticker:
          type: string
          description: "Stock ticker symbol, e.g. AAPL, GOOGL"
          required: true
      returns:
        type: object
        description: "Object with ticker, price, and currency"

    - name: translate
      custom: true
      description: "Translate text to a target language"
      category: text
      path: my_tools.py
      function_name: translate
      parameters:
        text:
          type: string
          description: "Text to translate"
          required: true
        target_lang:
          type: string
          description: "Target language code (en, he, fr, etc.)"
          required: false
          default: "en"
      returns:
        type: string
        description: "Translated text"
```

### Step 3: Done

The agent will now see these tools and can call them when needed. The LLM decides when to use them based on the `description` you provide.

---

## Creating New Built-in Tools

Built-in tools are shared across all agents. Each tool is a folder inside `tools/`.

### Step 1: Create the Folder

```
tools/
  my_new_tool/
    tool.yaml
    tool.py
```

### Step 2: Define `tool.yaml`

```yaml
name: my_new_tool
description: "Clear, concise description of what this tool does"
category: data
function_name: run

parameters:
  param_one:
    type: string
    description: "What this parameter is for"
    required: true
  param_two:
    type: number
    description: "Optional numeric parameter"
    required: false
    default: 10

returns:
  type: object
  description: "What the tool returns"
```

### Step 3: Implement `tool.py`

```python
# tools/my_new_tool/tool.py

def run(param_one: str, param_two: int = 10) -> dict:
    """
    The function name must match 'function_name' in tool.yaml.
    Parameter names must match 'parameters' in tool.yaml.
    """
    # your logic here
    result = do_something(param_one, param_two)
    return {"status": "success", "data": result}
```

### Step 4: Use it

```yaml
my_agent:
  model: gpt-4
  tools:
    - name: my_new_tool
      custom: false
```

---

## YAML Reference

### Tool Parameter Fields

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `type` | string | ✅ | `string`, `number`, `boolean`, `array`, `object` |
| `description` | string | ✅ | What this parameter is for (the LLM reads this) |
| `required` | boolean | ❌ | Default: `false` |
| `default` | any | ❌ | Default value if not provided |
| `enum` | array | ❌ | List of allowed values |

### Custom Tool Fields

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `name` | string | ✅ | Unique tool name |
| `custom` | boolean | ✅ | Must be `true` |
| `description` | string | ✅ | What the tool does (LLM uses this to decide when to call it) |
| `category` | string | ❌ | For organization: `search`, `math`, `data`, `finance`, etc. |
| `path` | string | ✅ | Path to `.py` file, relative to agent directory |
| `function_name` | string | ✅ | Function name inside the `.py` file |
| `parameters` | object | ✅ | Input parameters definition |
| `returns` | object | ❌ | Return value description |

### Built-in Tool Fields

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `name` | string | ✅ | Must match a folder name in `tools/` |
| `custom` | boolean | ✅ | Must be `false` |

---

## How It Works at Runtime

```
1. Agent loads         → ToolRegistry reads YAML, imports Python functions
2. Agent.run() called  → LLM receives tool schemas via API parameter
3. LLM wants a tool    → returns {"tool_calls": [{"name": "calculator", "arguments": {...}}]}
4. Agent executes      → ToolRegistry.execute("calculator", {...}) → runs Python function
5. Result sent back    → Added to messages as {"role": "tool", "content": "4.0"}
6. LLM sees result     → Either calls another tool or returns final answer
7. Loop limit          → Max 10 rounds (configurable via _max_tool_rounds)
```

## Tips

- **Write good descriptions** — the LLM decides when to use a tool based on the `description` field. Be clear and specific.
- **Keep tools focused** — one tool should do one thing. Better to have `search_web` and `search_docs` than one `search` tool that does everything.
- **Return structured data** — return dicts/lists rather than formatted strings. The LLM is better at interpreting structured data.
- **Handle errors** — if your tool fails, raise an exception with a clear message. The agent will pass the error back to the LLM so it can try again or respond accordingly.
- **Multiple functions in one file** — you can put several tool functions in the same `.py` file and reference different `function_name` values from different tool configs.

## Example: Full Agent with Tools

```
agents/
  researcher/
    config.yaml
    instruction.md
    custom_tools.py
    logs/
```

```yaml
# agents/researcher/config.yaml
researcher:
  agent_id: node_042
  model: gpt-4
  temperature: 0.2
  instruction_path: instruction.md
  return_format: json
  tools:
    - name: calculator
      custom: false
    - name: web_search
      custom: false
    - name: company_lookup
      custom: true
      description: "Look up company information by name or ticker"
      category: finance
      path: custom_tools.py
      function_name: lookup_company
      parameters:
        query:
          type: string
          description: "Company name or ticker symbol"
          required: true
      returns:
        type: object
        description: "Company info with name, sector, market_cap"
```

```markdown
<!-- agents/researcher/instruction.md -->
You are a financial research assistant.
Use the tools available to you to answer questions about companies and markets.
Always verify numbers with the calculator.
```

```python
# agents/researcher/custom_tools.py
def lookup_company(query: str) -> dict:
    # your implementation
    return {"name": "Apple Inc.", "sector": "Technology", "market_cap": "3.4T"}
```