Skip to content
Back to skills

Tool Augmented Models Training

ASecurity

Use when training models for tool-use and function calling.

  • 2 stars
  • 0 votes
  • 0 copies
  • 3 views
  • Added September 10, 2026
ai-agentspythongit

Security analysis

A100/100

Scanned September 10, 2026

npx -y skills add LoopyLuci/Skills --skill tool-augmented-models-training --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Tool Augmented Models Training?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Tool Augmented Models Training
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/loopyluci-tool-augmented-models-training/badge)](https://www.skillsdirectory.com/skills/loopyluci-tool-augmented-models-training)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: tool-augmented-models-training
description: "Use when training models for tool-use and function calling."
version: 1.0.0
author: Hermes Agent
license: MIT
metadata:
  hermes:
    tags: [tool-use, function-calling, training, fine-tuning, agents]
    related_skills: [tool-augmented-agents, agentic-models-from-scratch, rlhf-implementation-guide, agent-framework-design]
---

# Training Models for Tool Use and Function Calling

Strategies for training language models to use tools effectively — from data generation through fine-tuning to evaluation of tool-calling ability.

## When to Use

- Fine-tuning a model specifically for tool-use capability
- Generating synthetic tool-use training data
- Evaluating tool-calling accuracy and robustness
- Improving an existing agent's ability to select and use tools
- Building models that can handle dynamic, user-defined tools

## Training Data Generation

### Synthetic Data Pipeline

```python
import json
import random

class ToolUseDataGenerator:
    """Generate synthetic training data for tool-use behavior.
    
    Data format: conversation with interleaved tool calls.
    {
        "messages": [
            {"role": "system", "content": "You have access to tools..."},
            {"role": "user", "content": "What's the weather in Paris?"},
            {"role": "assistant", "content": "Let me check.", "tool_calls": [...]},
            {"role": "tool", "content": "72°F, sunny", "tool_call_id": "..."},
            {"role": "assistant", "content": "The weather in Paris is 72°F and sunny."}
        ]
    }
    """
    
    def __init__(self, tools, num_examples=10000):
        self.tools = tools
        self.num_examples = num_examples
    
    def generate_dataset(self):
        """Generate diverse tool-use examples."""
        examples = []
        
        # Pattern 1: Simple single-tool call
        for tool in self.tools:
            for _ in range(self.num_examples // len(self.tools) // 3):
                examples.append(self._single_tool_example(tool))
        
        # Pattern 2: Multi-tool chaining
        for _ in range(self.num_examples // 3):
            tools = random.sample(self.tools, min(3, len(self.tools)))
            examples.append(self._chained_tool_example(tools))
        
        # Pattern 3: Conditional tool use
        for _ in range(self.num_examples // 6):
            examples.append(self._conditional_tool_example())
        
        # Pattern 4: Error recovery
        for _ in range(self.num_examples // 6):
            examples.append(self._error_recovery_example())
        
        return examples
    
    def _single_tool_example(self, tool):
        """Generate a simple tool-use conversation."""
        user_intent = self._generate_user_intent(tool)
        return {
            "messages": [
                {"role": "system", "content": self._system_prompt()},
                {"role": "user", "content": user_intent},
                {"role": "assistant", "content": self._thinking_trace(tool), 
                 "tool_calls": [self._generate_tool_call(tool)]},
                {"role": "tool", "content": self._generate_tool_response(tool), 
                 "tool_call_id": "call_1"},
                {"role": "assistant", "content": self._final_response(tool)}
            ]
        }
    
    def _chained_tool_example(self, tools):
        """Generate multi-tool chain conversation."""
        messages = [{"role": "system", "content": self._system_prompt()}]
        messages.append({"role": "user", "content": f"Use {', '.join(t.name for t in tools)} to accomplish this task."})
        
        for i, tool in enumerate(tools):
            messages.append({
                "role": "assistant",
                "content": f"Using {tool.name}.", 
                "tool_calls": [self._generate_tool_call(tool)]
            })
            messages.append({
                "role": "tool",
                "content": self._generate_tool_response(tool),
                "tool_call_id": f"call_{i}"
            })
        
        messages.append({"role": "assistant", "content": "Task complete."})
        return {"messages": messages}
    
    def _system_prompt(self):
        tool_descriptions = "\n".join(
            f"- {t.name}: {t.description}" for t in self.tools
        )
        return f"""You are a helpful assistant with access to tools.
Available tools:
{tool_descriptions}

When you need to use a tool, output a JSON tool call.
After receiving the result, provide a helpful response."""
```

### Tool Definition Format

```python
TOOL_SCHEMA_TEMPLATE = {
    "type": "function",
    "function": {
        "name": "get_weather",
        "description": "Get current weather for a location",
        "parameters": {
            "type": "object",
            "properties": {
                "location": {
                    "type": "string",
                    "description": "City name, e.g., Paris, France"
                },
                "units": {
                    "type": "string",
                    "enum": ["celsius", "fahrenheit"],
                    "default": "celsius"
                }
            },
            "required": ["location"]
        }
    }
}
```

## Fine-Tuning Strategies

### Full Fine-Tuning

```python
def train_tool_use(model, dataset, tokenizer, epochs=3, lr=1e-5):
    """Fine-tune model on tool-use conversations."""
    from transformers import TrainingArguments, Trainer
    
    training_args = TrainingArguments(
        output_dir="./tool-model",
        per_device_train_batch_size=8,
        gradient_accumulation_steps=4,
        learning_rate=lr,
        num_train_epochs=epochs,
        logging_steps=10,
        save_steps=500,
        fp16=True,
    )
    
    def tokenize_function(examples):
        # Format messages into training sequences
        texts = []
        for conversation in examples['messages']:
            text = tokenizer.apply_chat_template(
                conversation,
                tokenize=False,
                add_generation_prompt=False
            )
            texts.append(text)
        
        return tokenizer(texts, truncation=True, padding=True, max_length=4096)
    
    trainer = Trainer(
        model=model,
        args=training_args,
        train_dataset=dataset.map(tokenize_function, batched=True),
    )
    
    trainer.train()
    return model
```

### LoRA Fine-Tuning

```python
from peft import LoraConfig, get_peft_model, TaskType

def lora_tune_tool_use(base_model):
    """Parameter-efficient fine-tuning for tool use.
    Only trains a small subset of parameters."""
    
    lora_config = LoraConfig(
        r=16,
        lora_alpha=32,
        target_modules=["q_proj", "v_proj", "k_proj", "o_proj"],
        lora_dropout=0.1,
        bias="none",
        task_type=TaskType.CAUSAL_LM
    )
    
    model = get_peft_model(base_model, lora_config)
    model.print_trainable_parameters()  # ~0.5% of params
    return model
```

### Multi-Task Training

```python
class ToolUseTrainer:
    """Multi-objective training for tool use.
    Balances: general LM loss + tool-call accuracy + response quality."""
    
    def compute_loss(self, model, batch):
        outputs = model(**batch)
        
        # Standard LM loss
        lm_loss = outputs.loss
        
        # Tool-call specific loss (masked: only on tool-call tokens)
        if 'tool_labels' in batch:
            tool_logits = outputs.logits[batch['tool_mask']]
            tool_loss = F.cross_entropy(tool_logits, batch['tool_labels'])
        else:
            tool_loss = 0
        
        return lm_loss + 0.5 * tool_loss
```

## Evaluation

```python
class ToolUseEvaluator:
    """Evaluates tool-calling accuracy across multiple dimensions."""
    
    def __init__(self, test_cases):
        self.test_cases = test_cases
    
    def evaluate(self, model):
        results = {
            'tool_selection_accuracy': 0,
            'parameter_fidelity': 0,
            'error_recovery_rate': 0,
            'response_quality': 0
        }
        
        for case in self.test_cases:
            # Test: model selects the right tool
            prediction = model.generate(case['prompt'])
            results['tool_selection_accuracy'] += self._check_tool_selection(prediction, case)
            
            # Test: parameters are correctly formatted
            results['parameter_fidelity'] += self._check_parameters(prediction, case)
            
            # Test: handles errors gracefully
            if case.get('error_scenario'):
                results['error_recovery_rate'] += self._check_error_recovery(prediction, case)
        
        n = len(self.test_cases)
        return {k: v / n for k, v in results.items()}
    
    def _check_tool_selection(self, prediction, case):
        """Verify correct tool was chosen."""
        return 1.0 if case['expected_tool'] in prediction else 0.0
    
    def _check_parameters(self, prediction, case):
        """Verify parameters match expected format."""
        import json, re
        calls = re.findall(r'\{[^}]+\}', prediction)
        if not calls:
            return 0.0
        
        try:
            call = json.loads(calls[0])
            expected = case['expected_params']
            matching = sum(1 for k, v in expected.items() 
                         if call.get(k) == v)
            return matching / len(expected) if expected else 1.0
        except:
            return 0.0
```

## Common Pitfalls

1. **Tool hallucination** — model invokes non-existent tools; always validate tool names server-side
2. **Parameter hallucination** — invents parameter names; train with strict schema adherence
3. **Forgetting to call tools** — model describes what it would do without actually calling; use system prompt pressure
4. **Over-reliance on tools** — model calls tools for questions it could answer directly; train for selective use
5. **Tool call formatting** — model produces near-valid but incorrect JSON; use constrained decoding
6. **Multi-turn state loss** — model forgets previous tool results; train with long contexts

## Verification Checklist

- [ ] Model selects correct tool for each test case
- [ ] Parameters match tool schema (names, types, required fields)
- [ ] Model correctly handles tool output in subsequent response
- [ ] Error handling graceful (malformed tool output doesn't crash)
- [ ] No tool hallucination (never calls unlisted tools)
- [ ] Multi-turn consistency (remembers previous tool results)
- [ ] Generic vs. specific tool distinction (chooses right granularity)

## See Also

- tool-augmented-agents — wrapping tool-use models in agent frameworks
- agentic-models-from-scratch — building models with native tool-awareness
- agent-framework-design — integrating tool calls in agent architecture
- rlhf-implementation-guide — aligning tool-use behavior

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.