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

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, 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—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 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.

  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:

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 and register it via the ToolRegistry:

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:

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

Frequently Asked Questions

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

The Agent class in 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, 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →