Simple Chatbot
Building on the Quick Start guide, this example explores the simple chatbot agent in more detail. The chatbot responds to user queries while demonstrating some basic DAD concepts like node flow and event handling.
Agent Structure
A simple chatbot agent consists of three main files:
- agent.py: Defines the agent structure
- flow.py: Contains the flow definition and nodes
- handler.py: Handles events like user input
Agent Definition
The agent definition file is straightforward, importing the flow and creating the agent:
from dhenara.agent.dsl import AgentDefinition
from .flow import main_flow
# Main Agent Definition
agent = AgentDefinition()
agent.flow(
"main_flow_1", # Flow instance ID
main_flow, # Flow definition
)
Flow Definition
The flow defines how the agent processes information:
from dhenara.agent.dsl import (
AIModelNode,
AIModelNodeSettings,
EventType,
FlowDefinition,
)
from dhenara.ai.types import AIModelCallConfig, Prompt
main_flow = FlowDefinition()
# First node - processes user input and generates response
main_flow.node(
"user_query_processor",
AIModelNode(
pre_events=[EventType.node_input_required],
settings=AIModelNodeSettings(
models=[
"claude-3-5-haiku",
"gpt-4.1-nano",
"gemini-2.0-flash-lite",
],
system_instructions=[
"You are an AI assistant in a general purpose chatbot",
"Always respond in plaintext format.",
],
prompt=Prompt.with_dad_text("$var{user_query}"),
model_call_config=AIModelCallConfig(
test_mode=False,
),
),
),
)
# Second node - generates a title for the conversation
main_flow.node(
"title_generator",
AIModelNode(
settings=AIModelNodeSettings(
models=["gpt-4o-mini"],
system_instructions=[
"You are a summarizer which generate a title.",
],
prompt=Prompt.with_dad_text(
"Summarize in plain text under 60 characters. $expr{ $hier{ai_model_call_1}.outcome.text }",
),
),
),
)
Event Handler
The handler processes input events triggered during flow execution:
from dhenara.agent.dsl import (
FlowNodeTypeEnum,
NodeInputRequiredEvent,
)
from dhenara.agent.utils.helpers.terminal import async_input, get_ai_model_node_input
async def node_input_event_handler(event: NodeInputRequiredEvent):
node_input = None
if event.node_type == FlowNodeTypeEnum.ai_model_call:
if event.node_id == "ai_model_call_1":
node_input = await get_ai_model_node_input(
node_def_settings=event.node_def_settings,
)
user_query = await async_input("Enter your query: ")
node_input.prompt_variables = {"user_query": user_query}
event.input = node_input
event.handled = True
Runner Script
To run the agent, you would use a runner script:
from dhenara.agent.dsl.events import EventType
from dhenara.agent.run import RunContext
from dhenara.agent.runner import AgentRunner
from dhenara.agent.utils.helpers.terminal import (
print_component_completion,
print_node_completion,
)
# Import the agent and handler
from src.agents.chatbot.agent import agent
from src.agents.chatbot.handler import node_input_event_handler
from src.runners.defs import project_root
# Define the root component ID
root_component_id = "chatbot_root"
agent.root_id = root_component_id
# Create run context
run_context = RunContext(
root_component_id=root_component_id,
project_root=project_root,
observability_settings=None, # Optional: add observability settings
run_root_subpath="agent_chatbot", # Optional: specify a path for run artifacts
)
# Register event handlers
run_context.register_event_handlers(
handlers_map={
EventType.node_input_required: node_input_event_handler,
EventType.node_execution_completed: print_node_completion,
EventType.component_execution_completed: print_component_completion,
}
)
# Create and run the agent
runner = AgentRunner(agent, run_context)
How It Works
- The flow starts execution, beginning with the
user_query_processor
node - This node triggers an
input_required
event, which is handled by thenode_input_event_handler
- The handler prompts the user for input and attaches it as a variable to the node
- The node uses the selected AI model to process the query and generate a response
- Next, the
title_generator
node runs, creating a title based on the first node's response - All results are stored in the run directory for future reference
Extending the Chatbot
You can extend this basic chatbot by:
- Adding more nodes to the flow for additional processing steps
- Incorporating memory using context variables to remember conversation history
- Integrating with external services or databases
- Adding specialized roles or capabilities through system instructions
This simple example demonstrates the fundamentals of creating an agent with DAD. The following examples will build on these concepts to create more complex agents.