๐ Overview
This intermediate tutorial demonstrates how to:
- Define multiple agent types (class-based, decorator-based)
- Use tools for data retrieval
- Use
custom_start
to override agent logic
- Orchestrate them in a flow using
TaskFlow
In this flow, a user input goes through three stages:
- ResearchAgent fetches content
- SummarizerAgent condenses it
- ReporterAgent formats the result as a final report
๐ฆ File Structure
from chainless import Tool
def mock_web_search(query: str) -> str:
return f"[MOCK] Web search results for: '{query}'"
web_tool = Tool(
name="WebSearch",
description="Searches the web for information on a given topic.",
func=mock_web_search
)
๐ง Step 2 โ ResearchAgent (Custom Start)
This agent uses the web tool and formats the tool result into a paragraph.
from chainless import Agent
from langchain_deepseek import ChatDeepSeek
llm = ChatDeepSeek(model="deepseek-chat")
research_agent = Agent(
name="ResearchAgent",
llm=llm,
tools=[web_tool],
system_prompt="You're a research assistant. Use the WebSearch tool if needed."
)
@research_agent.custom_start
def run_research(input: str, tools, llm, system_prompt):
tool_result = tools[0].execute({"query": input})
prompt = f"{system_prompt}nnTopic: {input}nnTool Output: {tool_result}nnWrite a research paragraph."
return llm.invoke(prompt)
๐งพ Step 3 โ SummarizerAgent (Standard)
summarizer_agent = Agent(
name="SummarizerAgent",
llm=llm,
system_prompt="Summarize the given research in a concise paragraph."
)
๐ค Step 4 โ ReporterAgent (AgentProtocol)
This agent implements AgentProtocol
and formats output as an email.
class ReporterAgent:
name = "ReporterAgent"
def start(self, input: str, **kwargs):
return {
"output": f"Subject: Weekly Research ReportnnDear Reader,nn{input}nnBest regards,nYour AI Assistant"
}
๐ Step 5 โ TaskFlow Assembly
from chainless import TaskFlow
flow = TaskFlow(name="ResearchReportFlow")
# Add agents
flow.add_agent("research", research_agent)
flow.add_agent("summarize", summarizer_agent)
flow.add_agent("report", ReporterAgent())
# Define steps
flow.step("research", {"input": "{{input}}"})
flow.step("summarize", {"input": "{{research.output}}"})
flow.step("report", {"input": "{{summarize.output}}"})
# Run
result = flow.run("The impact of AI in modern education")
print(result["output"])
โ
Output Sample
Subject: AI Weekly
Dear Reader,
[Summarized research content here...]
Yours,
ChainlessBot
๐ Notes
add_agent(name, agent)
registers agents
step(name, {inputs})
sets how data flows
- Use
{{previous.output}}
syntax for chaining outputs
- Agents can be class-based or decorator-based
๐งช Full Code: research_flow.py
from chainless import Tool, Agent, TaskFlow
from langchain_deepseek import ChatDeepSeek
# Tool
def mock_web_search(query: str) -> str:
return f"[MOCK] Web search results for: '{query}'"
web_tool = Tool(
name="WebSearch",
description="Searches the web for information on a given topic.",
func=mock_web_search
)
# LLM
llm = ChatDeepSeek(model="deepseek-chat")
# Research Agent
research_agent = Agent(
name="ResearchAgent",
llm=llm,
tools=[web_tool],
system_prompt="You're a research assistant. Use the WebSearch tool if needed."
)
@research_agent.custom_start
def run_research(input: str, tools, llm, system_prompt):
tool_result = tools[0].execute({"query": input})
prompt = f"{system_prompt}nnTopic: {input}nnTool Output: {tool_result}nnWrite a research paragraph."
return llm.invoke(prompt)
# Summarizer Agent
summarizer_agent = Agent(
name="SummarizerAgent",
llm=llm,
system_prompt="Summarize the given research in a concise paragraph."
)
# Reporter Agent using AgentProtocol
class ReporterAgent:
name = "ReporterAgent"
def start(self, input: str, **kwargs):
return {
"output": f"Subject: Weekly Research ReportnnDear Reader,nn{input}nnBest regards,nYour AI Assistant"
}
# Flow
flow = TaskFlow(name="ResearchReportFlow")
# Add agents
flow.add_agent("research", research_agent)
flow.add_agent("summarize", summarizer_agent)
flow.add_agent("report", ReporterAgent())
# Define steps
flow.step("research", {"input": "{{input}}"})
flow.step("summarize", {"input": "{{research.output}}"})
flow.step("report", {"input": "{{summarize.output}}"})
# Run
result = flow.run("The impact of AI in modern education")
print(result["output"])
โ
Output Example
[ResearchAgent] โ Research paragraph...
[SummarizerAgent] โ Concise summary...
[ReporterAgent] โ Formatted email report...
๐ง Takeaways
- Use
Tool
for modular utility
- Combine
Agent
types (class, decorator) for flexibility
- Extend with custom logic via
custom_start
- Chain steps clearly with
TaskFlow
๐ Next
- Add error handling, retries
- Split tasks conditionally
- Add memory/state passing between agents