From agno-framework
Build single Agno agents with tools, structured output, storage, memory, knowledge bases, guardrails, and human-in-the-loop confirmation. Trigger this skill when: importing agno.agent, creating an Agent instance, adding tools to an agent, configuring agent storage/memory, or asking "how do I build an agent with Agno?"
How this skill is triggered — by the user, by Claude, or both
Slash command
/agno-framework:agno-agentThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Use `agno.agent.Agent` to create AI agents. Install with `pip install agno`.
Use agno.agent.Agent to create AI agents. Install with pip install agno.
from agno.agent import Agent
from agno.models.anthropic import Claude
agent = Agent(
name="My Agent",
model=Claude(id="claude-sonnet-4-5"),
instructions=["Be concise.", "Use tables for data."],
markdown=True,
)
agent.print_response("Hello!", stream=True)
Agent(
name="Agent Name",
model=Claude(id="claude-sonnet-4-5"), # Required: model provider
instructions="System prompt or list", # str or list[str]
tools=[ToolKit(), func], # Tools the agent can call
markdown=True, # Format output as markdown
show_tool_calls=True, # Display tool invocations
add_datetime_to_context=True, # Inject current datetime
add_history_to_context=True, # Include conversation history
num_history_runs=5, # How many prior runs to include
db=SqliteDb(db_file="agent.db"), # Persistent storage backend
)
Give agents tools to interact with external data and services.
from agno.agent import Agent
from agno.models.anthropic import Claude
from agno.tools.yfinance import YFinanceTools
agent = Agent(
name="Finance Agent",
model=Claude(id="claude-sonnet-4-5"),
tools=[YFinanceTools()],
instructions="You are a data-driven financial analyst.",
add_datetime_to_context=True,
markdown=True,
)
agent.print_response("Give me a quick investment brief on NVIDIA", stream=True)
Use output_schema with a Pydantic model to get typed responses.
from typing import List, Optional
from pydantic import BaseModel, Field
from agno.agent import Agent
from agno.models.anthropic import Claude
from agno.tools.yfinance import YFinanceTools
class StockAnalysis(BaseModel):
ticker: str = Field(..., description="Stock ticker symbol")
current_price: float = Field(..., description="Current price in USD")
summary: str = Field(..., description="One-line summary")
key_risks: List[str] = Field(..., description="2-3 key risks")
recommendation: str = Field(..., description="Buy, Hold, or Sell")
agent = Agent(
name="Analyst",
model=Claude(id="claude-sonnet-4-5"),
tools=[YFinanceTools()],
output_schema=StockAnalysis,
markdown=True,
)
response = agent.run("Analyze NVIDIA")
analysis: StockAnalysis = response.content
print(f"Price: ${analysis.current_price:.2f}")
print(f"Recommendation: {analysis.recommendation}")
Use input_schema + output_schema for end-to-end type safety.
from typing import List, Literal, Optional
from pydantic import BaseModel, Field
from agno.agent import Agent
from agno.models.anthropic import Claude
class AnalysisRequest(BaseModel):
ticker: str = Field(..., description="Stock ticker symbol")
analysis_type: Literal["quick", "deep"] = Field(default="quick")
class AnalysisResult(BaseModel):
ticker: str
summary: str
recommendation: str
agent = Agent(
name="Typed Agent",
model=Claude(id="claude-sonnet-4-5"),
input_schema=AnalysisRequest,
output_schema=AnalysisResult,
)
# Pass input as dict or Pydantic model
response = agent.run(input={"ticker": "NVDA", "analysis_type": "deep"})
result: AnalysisResult = response.content
Add db= to persist conversation history across runs. Use session_id to maintain conversation threads.
from agno.agent import Agent
from agno.models.anthropic import Claude
from agno.db.sqlite import SqliteDb
agent = Agent(
name="Persistent Agent",
model=Claude(id="claude-sonnet-4-5"),
db=SqliteDb(db_file="tmp/agents.db"),
add_history_to_context=True,
num_history_runs=5,
)
# Same session_id = continuous conversation
agent.print_response("Hello!", session_id="my-session", stream=True)
agent.print_response("What did I just say?", session_id="my-session", stream=True)
Memory persists user-level facts across all sessions. Different from storage (conversation history).
from agno.agent import Agent
from agno.models.anthropic import Claude
from agno.db.sqlite import SqliteDb
from agno.memory import MemoryManager
db = SqliteDb(db_file="tmp/agents.db")
memory_manager = MemoryManager(
model=Claude(id="claude-sonnet-4-5"),
db=db,
additional_instructions="Capture user preferences and goals.",
)
agent = Agent(
name="Memory Agent",
model=Claude(id="claude-sonnet-4-5"),
db=db,
memory_manager=memory_manager,
enable_agentic_memory=True, # Agent decides when to store/recall
# OR: update_memory_on_run=True # Always run memory manager (guaranteed but slower)
add_history_to_context=True,
num_history_runs=5,
)
agent.print_response("I prefer tech stocks", user_id="[email protected]", stream=True)
memories = agent.get_user_memories(user_id="[email protected]")
Use session_state for structured data the agent actively manages (watchlists, counters, flags).
from agno.agent import Agent
from agno.models.anthropic import Claude
from agno.db.sqlite import SqliteDb
from agno.run import RunContext
def add_item(run_context: RunContext, item: str) -> str:
"""Add an item to the list."""
items = run_context.session_state.get("items", [])
items.append(item)
run_context.session_state["items"] = items
return f"Added {item}. Total: {len(items)}"
agent = Agent(
name="Stateful Agent",
model=Claude(id="claude-sonnet-4-5"),
tools=[add_item],
session_state={"items": []},
add_session_state_to_context=True,
db=SqliteDb(db_file="tmp/agents.db"),
instructions="Current items: {items}", # State injected into instructions
)
Access state: agent.get_session_state() or response.session_state.
Give agents searchable document collections using vector databases.
from agno.agent import Agent
from agno.models.anthropic import Claude
from agno.db.sqlite import SqliteDb
from agno.knowledge.knowledge import Knowledge
from agno.knowledge.embedder.google import GeminiEmbedder
from agno.vectordb.chroma import ChromaDb
from agno.vectordb.search import SearchType
db = SqliteDb(db_file="tmp/agents.db")
knowledge = Knowledge(
name="My Docs",
vector_db=ChromaDb(
name="docs",
collection="docs",
path="tmp/chromadb",
persistent_client=True,
search_type=SearchType.hybrid,
embedder=GeminiEmbedder(id="gemini-embedding-001"),
),
max_results=5,
contents_db=db,
)
agent = Agent(
name="Knowledge Agent",
model=Claude(id="claude-sonnet-4-5"),
knowledge=knowledge,
search_knowledge=True, # Agent searches knowledge automatically
db=db,
)
# Load documents
knowledge.insert(name="Docs", url="https://docs.agno.com/introduction.md")
agent.print_response("What is Agno?", stream=True)
Validate input before processing using pre_hooks.
from agno.agent import Agent
from agno.models.anthropic import Claude
from agno.guardrails import PIIDetectionGuardrail, PromptInjectionGuardrail
from agno.guardrails.base import BaseGuardrail
from agno.exceptions import InputCheckError
from agno.run.agent import RunInput
class SpamGuardrail(BaseGuardrail):
def check(self, run_input):
content = run_input.input_content_string()
if content.count("!") > 5:
raise InputCheckError("Input appears to be spam")
async def async_check(self, run_input):
self.check(run_input)
agent = Agent(
name="Safe Agent",
model=Claude(id="claude-sonnet-4-5"),
pre_hooks=[
PIIDetectionGuardrail(),
PromptInjectionGuardrail(),
SpamGuardrail(),
],
)
Require user confirmation before executing sensitive tools.
from agno.agent import Agent
from agno.models.anthropic import Claude
from agno.tools import tool
@tool(requires_confirmation=True)
def delete_record(record_id: str) -> str:
"""Delete a record. Requires user confirmation."""
return f"Deleted record {record_id}"
agent = Agent(
name="Careful Agent",
model=Claude(id="claude-sonnet-4-5"),
tools=[delete_record],
)
response = agent.run("Delete record ABC-123")
# Check for pending confirmations
if response.active_requirements:
for req in response.active_requirements:
if req.needs_confirmation:
req.confirm() # or req.reject()
# Resume execution
response = agent.continue_run(
run_id=response.run_id,
requirements=response.requirements,
)
Swap models by changing the import and model ID:
from agno.models.anthropic import Claude
model = Claude(id="claude-sonnet-4-5")
from agno.models.openai import OpenAIChat
model = OpenAIChat(id="gpt-4o")
from agno.models.google import Gemini
model = Gemini(id="gemini-2.0-flash")
from agno.models.ollama import Ollama
model = Ollama(id="llama3.3")
add_history_to_context=True if you want conversational agents that remember prior messagesdb= if you want sessions to persist across script restartsOpenAIChat when you want the newer Responses API — use OpenAIResponses insteadagent.arun() and agent.aprint_response() for asyncpip install "agno[anthropic]" for Claude, pip install "agno[openai]" for OpenAIFor extended API patterns and advanced configuration, read references/api-patterns.md.
npx claudepluginhub ajshedivy/agno-cookbook --plugin agno-frameworkGuides AI agent development using ReAct, plan-and-execute, multi-agent architectures. Designs tools, memory systems, guardrails; orchestrates with LangChain, LlamaIndex, CrewAI, AutoGen.
Guides creation and configuration of autonomous agents for Claude Code plugins, covering frontmatter, triggering descriptions, system prompts, tools, teams, permissions, and best practices.