# How to Customize an Agent in Hello-Agents: A Complete Guide

> Learn to customize an agent in Hello-Agents by subclassing SimpleAgent and overriding key methods. Explore tool registry and enhance your agent's functionality seamlessly.

- Repository: [Datawhale/hello-agents](https://github.com/datawhalechina/hello-agents)
- Tags: how-to-guide
- Published: 2026-05-09

---

**To customize an agent in hello-agents, subclass `SimpleAgent` from the framework's agent module and override specific methods such as `_get_enhanced_system_prompt`, `_parse_tool_calls`, or the `run` loop, while registering custom tools through the `ToolRegistry`.**

The hello-agents framework provides a lightweight, extensible architecture for building conversational AI agents. At its core lies the `Agent` base class in [`core/agent.py`](https://github.com/datawhalechina/hello-agents/blob/main/core/agent.py), which handles message history and basic execution flow. Most developers customize an agent in hello-agents by extending `SimpleAgent`—a concrete implementation found in [`Co-creation-projects/YYHDBL-HelloCodeAgentCli/agents/simple_agent.py`](https://github.com/datawhalechina/hello-agents/blob/main/Co-creation-projects/YYHDBL-HelloCodeAgentCli/agents/simple_agent.py)—allowing you to modify system prompts, tool parsing logic, and execution behavior without modifying the underlying framework code.

## Understanding the Agent Architecture

Before customizing, you need to understand how the framework processes conversations. The `SimpleAgent` class orchestrates LLM interactions through a defined lifecycle: initialization, prompt enrichment, tool parsing, execution, and iteration.

### Core Components

The `Agent` base class in [`core/agent.py`](https://github.com/datawhalechina/hello-agents/blob/main/core/agent.py) defines the interface for message handling and history management. The `SimpleAgent` implementation extends this with concrete tool-calling capabilities. When initialized via `__init__`, it stores the LLM instance, system prompt, an optional `ToolRegistry`, and the `enable_tool_calling` flag that activates tool support only when a registry is provided.

### The Execution Flow

During the `run` method, the agent builds a message list and enters an iterative loop (up to `max_tool_iterations`). It first calls `_get_enhanced_system_prompt` to construct the system message—appending an "Available Tools" section when tools are enabled. After receiving the LLM response, `_parse_tool_calls` scans for patterns like `[TOOL_CALL:tool_name:parameters]`. Valid calls trigger `_execute_tool_call`, which resolves the tool from the registry, parses parameters via `_parse_tool_parameters`, optionally invokes a `tool_confirm_callback` for user approval, and injects the result back into the conversation history.

## Step-by-Step Guide to Customize an Agent in Hello-Agents

Custom agents are created by subclassing and method overriding. Here is the proven approach used in the repository's examples, particularly in [`code/chapter7/my_simple_agent.py`](https://github.com/datawhalechina/hello-agents/blob/main/code/chapter7/my_simple_agent.py).

1. **Subclass SimpleAgent**: Create a new class that inherits from `SimpleAgent` or the base `Agent` class.

2. **Override `__init__`**: Add custom attributes such as additional LLM clients, configuration objects, or logging handlers while calling `super().__init__()` to preserve base functionality.

3. **Modify System Prompts**: Redefine `_get_enhanced_system_prompt` to inject custom instructions, domain context, or output format requirements.

4. **Customize Tool Parsing**: Override `_parse_tool_calls` to support alternative syntaxes such as JSON-formatted tool calls instead of the default bracketed format.

5. **Register Tools**: Use `add_tool` or directly manipulate the `ToolRegistry` to expose new capabilities to the agent.

6. **Control Execution**: Provide a `tool_confirm_callback` during construction to enable interactive approval, or override `stream_run` for streaming responses.

## Code Examples for Custom Agents

The following implementations demonstrate specific customization patterns found in the datawhalechina/hello-agents repository.

### Customizing the System Prompt

Override `_get_enhanced_system_prompt` to append domain-specific instructions while preserving tool descriptions:

```python
from hello_agents import SimpleAgent, HelloAgentsLLM, Config, Message

class CustomAgent(SimpleAgent):
    def _get_enhanced_system_prompt(self) -> str:
        base = super()._get_enhanced_system_prompt()
        # Add a domain‑specific instruction

        extra = "\n\n## Extra Instructions\nYou must answer in JSON format."

        return base + extra

```

This approach leverages the existing prompt-building logic in `SimpleAgent` (lines 43-78) while injecting your custom requirements.

### Adding a Domain-Specific Calculator Tool

Create a tool by subclassing `Tool` from [`hello_agents/tools/base.py`](https://github.com/datawhalechina/hello-agents/blob/main/hello_agents/tools/base.py) and register it via the `ToolRegistry`:

```python
from hello_agents import SimpleAgent, HelloAgentsLLM, Config
from hello_agents.tools.base import Tool, Parameter
from Co-creation-projects.YYHDBL-HelloCodeAgentCli.tools.registry import ToolRegistry

class CalculatorTool(Tool):
    name = "calculator"
    description = "Perform arithmetic operations."
    parameters = [
        Parameter(name="expression", type="string", required=True,
                  description="A Python‑compatible arithmetic expression, e.g. '3*4+5'")
    ]

    def run(self, args: dict) -> str:
        expr = args["expression"]
        try:
            return str(eval(expr))
        except Exception as e:
            return f"Error: {e}"

# Build the agent

llm = HelloAgentsLLM(...)
registry = ToolRegistry()
registry.register_tool(CalculatorTool())

agent = SimpleAgent(
    name="CalcAgent",
    llm=llm,
    tool_registry=registry,
    enable_tool_calling=True,
)

print(agent.run("What is 7*8? Use the calculator tool."))

```

The agent expects tool calls in the format `[TOOL_CALL:calculator:expression=7*8]`, which `_parse_tool_calls` extracts and `_execute_tool_call` processes.

### Modifying Tool Call Parsing for JSON

Change the parsing logic to accept JSON payloads instead of the default bracketed syntax:

```python
import json
from hello_agents import SimpleAgent

class JsonToolAgent(SimpleAgent):
    def _parse_tool_calls(self, text: str) -> list:
        # Look for JSON blocks like {"tool":"search","params":{...}}

        calls = []
        try:
            data = json.loads(text)
            if isinstance(data, dict) and "tool" in data:
                calls.append({
                    "tool_name": data["tool"],
                    "parameters": json.dumps(data.get("params", {})),
                    "original": text
                })
        except json.JSONDecodeError:
            pass
        return calls

```

This override replaces the default regex-based parser in `SimpleAgent` (lines 80-92) while maintaining compatibility with the execution pipeline in `_execute_tool_call`.

## Summary

- **Subclass `SimpleAgent`** located in [`Co-creation-projects/YYHDBL-HelloCodeAgentCli/agents/simple_agent.py`](https://github.com/datawhalechina/hello-agents/blob/main/Co-creation-projects/YYHDBL-HelloCodeAgentCli/agents/simple_agent.py) to create custom agent behaviors.
- **Override `_get_enhanced_system_prompt`** to modify system instructions and tool descriptions sent to the LLM.
- **Customize `_parse_tool_calls`** to support alternative tool invocation formats like JSON or XML.
- **Use `ToolRegistry`** from [`Co-creation-projects/YYHDBL-HelloCodeAgentCli/tools/registry.py`](https://github.com/datawhalechina/hello-agents/blob/main/Co-creation-projects/YYHDBL-HelloCodeAgentCli/tools/registry.py) to register new tools via `register_tool` or `add_tool`.
- **Control execution flow** by setting `max_tool_iterations`, providing `tool_confirm_callback` for approval workflows, or overriding `stream_run` for real-time output.
- **Reference `MySimpleAgent`** in [`code/chapter7/my_simple_agent.py`](https://github.com/datawhalechina/hello-agents/blob/main/code/chapter7/my_simple_agent.py) for a complete example implementing streaming and helper methods.

## Frequently Asked Questions

### What is the difference between Agent and SimpleAgent in hello-agents?

The `Agent` class in [`core/agent.py`](https://github.com/datawhalechina/hello-agents/blob/main/core/agent.py) is an abstract base that provides message history management and basic execution interfaces. `SimpleAgent` is a concrete implementation that adds tool-calling capabilities, system prompt enrichment, and an iterative execution loop. Most customizations should subclass `SimpleAgent` rather than the base `Agent` to inherit the tool-handling infrastructure.

### How do I add authentication or confirmation before a tool executes?

Pass a `tool_confirm_callback` function during `SimpleAgent` initialization. This callback receives the tool name and parameters, allowing you to prompt the user for approval or validate permissions before `_execute_tool_call` runs the tool. If the callback returns `False`, the tool execution is skipped.

### Can I use multiple LLM providers in a single custom agent?

Yes. Override `__init__` in your subclass to accept multiple LLM instances (e.g., one for reasoning, one for formatting) and store them as instance attributes. You can then reference these specific LLMs in overridden methods when you need specialized processing, while keeping the primary `self.llm` for the main conversation flow.

### Where can I find a complete working example of a customized agent?

The repository provides `MySimpleAgent` in [`code/chapter7/my_simple_agent.py`](https://github.com/datawhalechina/hello-agents/blob/main/code/chapter7/my_simple_agent.py), which demonstrates extending `SimpleAgent` with streaming support (`stream_run` method), additional helper methods, and custom initialization patterns. This file serves as the reference implementation for production customizations.