Take a guided tour through the BeeAI Framework, building agents from the basics to advanced capabilities
This step-by-step guide shows how to start with your first agent and progressively add tools, debugging, reasoning, knowledge, and more. Each section introduces a single capability, so you can follow the full path or jump to the parts most useful to you.
Let’s start with the simplest possible agent - one that can respond to messages.
Copy
Ask AI
import asyncio from beeai_framework.agents.experimental import RequirementAgentfrom beeai_framework.backend import ChatModelasync def main(): agent = RequirementAgent( llm=ChatModel.from_name("ollama:granite3.3:8b"), role="friendly AI assistant", instructions="Be helpful and conversational in all your interactions." ) response = await agent.run("Hello! What can you help me with?") print(response.last_message.text)if __name__ == "__main__": asyncio.run(main())
Try it:
Save as simple_agent.py
Run python simple_agent.py
Test different prompts
Troubleshooting
Ollama not responding?
Verify it’s running: ollama list
Start the service: ollama serve
Model not found?
Pull the model: ollama pull granite3.3:8b
List available models: ollama list
Import errors?
Update to the latest version: pip install --upgrade beeai-framework
Check Python version: python --version (must be >= 3.11)
Give your agent the ability to access real-world information by adding tools.
Copy
Ask AI
import asyncio from beeai_framework.agents.experimental import RequirementAgentfrom beeai_framework.backend import ChatModelfrom beeai_framework.tools.search.wikipedia import WikipediaToolfrom beeai_framework.tools.weather import OpenMeteoToolasync def main(): agent = RequirementAgent( llm=ChatModel.from_name("ollama:granite3.3:8b"), role="friendly AI assistant", instructions="Be helpful and conversational in all your interactions. Use your tools to find accurate, current information.", tools=[WikipediaTool(), OpenMeteoTool()], ) response = await agent.run("What's the current weather in New York and tell me about the history of the city?") print(response.last_message.text)if __name__ == "__main__": asyncio.run(main())
Try these prompts:
“What’s the weather in different cities around the world?”
“Tell me about quantum computing and the current weather in CERN’s location”
“Compare the weather in New York and London, then tell me about their historical relationship”
Knowing what your application is doing is essential from the very start.
The BeeAI Framework is based on the event system; each component in the framework emits events throughout its execution.
You can listen and alter these events to build custom logic.
The most simple way to see what’s happening in your application is by using GlobalTrajectoryMiddleware which listens to all events and prints them to the console.
Copy
Ask AI
import asynciofrom beeai_framework.agents.experimental import RequirementAgentfrom beeai_framework.backend import ChatModelfrom beeai_framework.tools.weather import OpenMeteoToolfrom beeai_framework.middleware.trajectory import GlobalTrajectoryMiddlewarefrom beeai_framework.tools import Toolasync def main(): agent = RequirementAgent( llm=ChatModel.from_name("ollama:granite3.3:8b"), tools=[OpenMeteoTool()] ) response = await agent .run("What's the current weather in Paris?") .middleware(GlobalTrajectoryMiddleware( included=[Tool], # Only show tool executions )) print(response.last_message.text)if __name__ == "__main__": asyncio.run(main())
Middlewares can be used either on the run level (as shown above) or can be bind to the class directly by passing them in the class constructor as a keyword argument called middlewares.
All events and appropriate typings are stored in the events.py file in the given module.
All emitters inherit from the root emitter, which is accessible through Emitter.root() which you can use to monitor all events happening in the application.
Use this for: When you want to log specific events in your application codeHow it works: You manually write logging statements wherever you want them
Copy
Ask AI
import asyncio from beeai_framework.agents.experimental import RequirementAgentfrom beeai_framework.backend import ChatModelfrom beeai_framework.tools.search.wikipedia import WikipediaToolfrom beeai_framework.tools.weather import OpenMeteoToolfrom beeai_framework.middleware.trajectory import GlobalTrajectoryMiddlewarefrom beeai_framework.tools import Toolfrom beeai_framework.logger import Loggerasync def main(): # You create the logger and decide what to log logger = Logger("my-agent", level="TRACE") logger.info("Starting agent application") agent = RequirementAgent( llm=ChatModel.from_name("ollama:granite3.3:8b"), role="friendly AI assistant", instructions="Be helpful and conversational in all your interactions. Use your tools to find accurate, current information.", tools=[WikipediaTool(), OpenMeteoTool()] ) logger.debug("About to process user message") # The `included` parameter filters what types of operations to trace: # - [Tool]: Show only tool executions (function calls, API calls, etc.) # - [ChatModel]: Show only LLM calls (model inference, token usage) # - [Tool, ChatModel]: Show both tools and LLM interactions # - [] or None: Show everything (agents, tools, models, requirements) response = await agent.run( "What's the weather in Paris and tell me about the Eiffel Tower?" ).middleware(GlobalTrajectoryMiddleware(included=[Tool])) logger.info("Agent response generated") print(response.last_message.text)if __name__ == "__main__": asyncio.run(main())
What you see: Traditional log messages with timestamps
Copy
Ask AI
2024-01-15 10:30:45 | INFO | my-agent - Starting agent application2024-01-15 10:30:45 | DEBUG | my-agent - About to process user message 2024-01-15 10:30:47 | INFO | my-agent - Agent response generated successfully
Logging to the console is great for development, but it’s not enough for production monitoring. You can easily let
the framework send traces and metrics to external platforms like Arize Phoenix, LangFuse, LangSmith, and more.
Install the extras if you haven’t already: pip install openinference-instrumentation-beeai
Don’t forget to set the following environment variable OTEL_EXPORTER_OTLP_ENDPOINT.
Use Requirements to control your agent’s behavior. Let’s add the Think Tool and set up some conditional requirements to decide when tools should run.
Copy
Ask AI
import asyncio from beeai_framework.agents.experimental import RequirementAgentfrom beeai_framework.agents.experimental.requirements.conditional import ConditionalRequirementfrom beeai_framework.backend import ChatModelfrom beeai_framework.tools.search.wikipedia import WikipediaToolfrom beeai_framework.tools.weather import OpenMeteoToolfrom beeai_framework.tools.think import ThinkToolfrom beeai_framework.middleware.trajectory import GlobalTrajectoryMiddlewarefrom beeai_framework.tools import Toolfrom beeai_framework.logger import Loggerasync def main(): logger = Logger("my-agent", level="TRACE") logger.info("Starting agent application") agent = RequirementAgent( llm=ChatModel.from_name("ollama:granite3.3:8b"), role="friendly AI assistant", instructions="Be helpful and conversational in all your interactions. Use your tools to find accurate, current information.", tools=[WikipediaTool(), OpenMeteoTool(), ThinkTool()], requirements=[ # Force agent to think before acting, and after each tool use ConditionalRequirement( ThinkTool, force_at_step=1, # Always think first force_after=Tool, # Think after using any tool consecutive_allowed=False # Don't think twice in a row ) ], middlewares=[GlobalTrajectoryMiddleware(included=[Tool])] ) logger.debug("About to process user message") response = await agent.run( "What's the weather in Paris and tell me about the Eiffel Tower?" ) logger.info("Agent response generated") logger.info(response.last_message.text)if __name__ == "__main__": asyncio.run(main())
Learn more about Requirements and see examples in documentation
import asynciofrom beeai_framework.agents.experimental import RequirementAgentfrom beeai_framework.backend import ChatModelfrom beeai_framework.tools.search.wikipedia import WikipediaToolfrom beeai_framework.tools.weather import OpenMeteoToolfrom beeai_framework.tools.search.retrieval import VectorStoreSearchTool# Import the setup function from Step 1from step1_knowledge_base import setup_knowledge_base, load_documentsasync def main(): # Setup knowledge base (from Step 1) vector_store, text_splitter = await setup_knowledge_base() # Load your documents file_paths = [ "your_document1.md", "your_document2.md", ] loaded_vector_store = await load_documents(vector_store, text_splitter, file_paths) if not loaded_vector_store: print("No documents loaded - exiting") return # Create RAG tool rag_tool = VectorStoreSearchTool(vector_store=loaded_vector_store) # Create agent with RAG capabilities agent = RequirementAgent( llm=ChatModel.from_name("ollama:granite3.3:8b"), tools=[WikipediaTool(), OpenMeteoTool(), rag_tool], instructions="""You are a knowledgeable assistant with access to: 1. A document knowledge base (use VectorStoreSearch for specific document queries) 2. Wikipedia for general facts 3. Weather information When users ask about topics that might be in the documents, search your knowledge base first.""" ) # Test the RAG-enabled agent response = await agent.run("What information do you have in your knowledge base?") print(response.last_message.text)if __name__ == "__main__": asyncio.run(main())
Add some markdown files with information about your company/project
Ask questions that should be answered from your documents
Compare how responses differ with vs. without the knowledge base
Install the RAG extras if you haven’t already: pip install 'beeai-framework[rag]'
Create a team of specialized agents that can collaborate:
Copy
Ask AI
import asynciofrom beeai_framework.agents.experimental import RequirementAgentfrom beeai_framework.backend import ChatModelfrom beeai_framework.memory import UnconstrainedMemoryfrom beeai_framework.tools.search.wikipedia import WikipediaToolfrom beeai_framework.tools.weather import OpenMeteoToolfrom beeai_framework.tools.handoff import HandoffToolfrom beeai_framework.tools.think import ThinkToolfrom beeai_framework.logger import Loggerasync def main(): # Initialize logger logger = Logger("multi-agent-system", level="TRACE") logger.info("Starting multi-agent system") # Create specialized agents logger.debug("Creating knowledge agent") knowledge_agent = RequirementAgent( llm=ChatModel.from_name("ollama:granite3.3:8b"), tools=[ThinkTool(), WikipediaTool()], memory=UnconstrainedMemory(), instructions="Provide detailed, accurate information using available knowledge sources. Think through problems step by step." ) logger.debug("Creating weather agent") weather_agent = RequirementAgent( llm=ChatModel.from_name("ollama:granite3.3:8b"), tools=[ThinkTool(), OpenMeteoTool()], memory=UnconstrainedMemory(), instructions="Provide comprehensive weather information and forecasts. Always think before using tools." ) # Create a coordinator agent that manages handoffs logger.debug("Creating coordinator agent") coordinator_agent = RequirementAgent( llm=ChatModel.from_name("ollama:granite3.3:8b"), memory=UnconstrainedMemory(), tools=[ HandoffTool( target=knowledge_agent, name="knowledge_specialist", description="For general knowledge and research questions" ), HandoffTool( target=weather_agent, name="weather_expert", description="For weather-related queries" ), ], instructions="""You coordinate between specialist agents. - For weather queries: use weather_expert - For research/knowledge questions: use knowledge_specialist - For mixed queries: break them down and use multiple specialists Always introduce yourself and explain which specialist will help.""" ) logger.info("Running query: What's the weather in Paris and tell me about its history?") try: response = await coordinator_agent.run("What's the weather in Paris and tell me about its history?") logger.info("Query completed successfully") print(response.last_message.text) except Exception as e: logger.error(f"Error during agent execution: {e}") raise logger.info("Multi-agent system execution completed")if __name__ == "__main__": asyncio.run(main())
Ask the coordinator mixed questions: “What’s the weather in Paris and tell me about its history?”
Test how it decides which agent to use
Try complex queries that need multiple specialists
Caching helps you cut costs, reduce latency, and deliver consistent results by reusing previous computations. In BeeAI Framework, you can cache LLM responses and tool outputs.
Caching the entire agent isn’t practical—every agent run is usually unique. Instead, focus on caching the components inside your agent.
1. Caching LLM CallsConfigure a cache on your LLM to avoid paying for repeated queries:
Copy
Ask AI
import asynciofrom beeai_framework.backend import ChatModelfrom beeai_framework.cache import SlidingCacheasync def main(): # LLM with caching enabled llm = ChatModel.from_name("ollama:granite3.3:8b") llm.config(cache=SlidingCache(size=50)) # Cache up to 50 responses # First call (miss) res1 = await llm.chat("Hello! How are you today?") # Second call with identical input (hit) res2 = await llm.chat("Hello! How are you today?") print("First:", res1.text) print("Second (cached):", res2.text)asyncio.run(main())
2. Caching Tool OutputsMany tools query APIs or perform expensive lookups. You can attach a cache directly:
Copy
Ask AI
from beeai_framework.tools.weather import OpenMeteoToolfrom beeai_framework.cache import UnconstrainedCache# Cache all results from the weather APIweather_tool = OpenMeteoTool(options={"cache": UnconstrainedCache()})
3. Using Cached Components in an Agent
Copy
Ask AI
from beeai_framework.agents.experimental import RequirementAgentfrom beeai_framework.memory import UnconstrainedMemoryagent = RequirementAgent( llm=llm, # LLM with cache tools=[weather_tool], # Tool with cache memory=UnconstrainedMemory(), instructions="Provide answers efficiently using cached results when possible.")response1 = await agent.run("What's the weather in New York?")response2 = await agent.run("What's the weather in New York?") # Weather tool cache should hit
Agent-level caching is rarely effective because every input is usually unique. Focus on caching LLMs and tools individually for best performance.
from beeai_framework.adapters.mcp import MCPServerfrom beeai_framework.tools.weather import OpenMeteoToolfrom beeai_framework.tools.search.wikipedia import WikipediaTooldef main(): # Create an MCP server server = MCPServer() # Register tools that can be used by MCP clients server.register_many([ OpenMeteoTool(), WikipediaTool() ]) # Start the server server.serve()if __name__ == "__main__": main()
from beeai_framework.adapters.a2a import A2AServer, A2AServerConfigfrom beeai_framework.agents.experimental import RequirementAgentfrom beeai_framework.backend import ChatModelfrom beeai_framework.memory import UnconstrainedMemoryfrom beeai_framework.serve.utils import LRUMemoryManagerfrom beeai_framework.tools.search.duckduckgo import DuckDuckGoSearchToolfrom beeai_framework.tools.weather import OpenMeteoTooldef main() -> None: llm = ChatModel.from_name("ollama:granite3.3:8b") agent = RequirementAgent( llm=llm, tools=[DuckDuckGoSearchTool(), OpenMeteoTool()], memory=UnconstrainedMemory(), ) # Register the agent with the A2A server and run the HTTP server # we use LRU memory manager to keep limited amount of sessions in the memory A2AServer(config=A2AServerConfig(port=9999), memory_manager=LRUMemoryManager(maxsize=100)).register(agent).serve()if __name__ == "__main__": main()
Congratulations! You’ve built a complete AI agent system from a simple chat bot to a production-ready, multi-agent workflow with knowledge bases, caching, error handling, and service endpoints.Each module page includes detailed guides, examples, and best practices. Here are some next steps:
Explore Modules: Dive deeper into specific modules that interest you
Scale Your System: Add more agents, tools, and knowledge bases
Custom Tools: Build your own tools for domain-specific functionality
The framework is designed to scale with you—start small, then grow your system step by step as your needs evolve. You now have all the building blocks to create sophisticated AI agent systems!