Crafting Your Agent π οΈ
Three ingredients make a great agent: a local model, custom tools, and solid instructions.
Building agents doesn't need to be over-engineered. We recommend starting with a simple recipe: a model, some tools, and direct instructions. Once the basics are humming, you can layer in memory, databases, and structured schemas.
Here's the simplest agent with access to HackerNews, connected to a local Ollama server running Llama 3.2 3B:
1from kern.agent import Agent2from kern.models.openai import OpenAIChat3from kern.tools.hackernews import HackerNewsTools45# Let's boot up our local-first helper π€6agent = Agent(7 model=OpenAIChat(8 id="llama3.2:3b",9 base_url="http://localhost:11434/v1", # Hello, Ollama! π10 ),11 tools=[HackerNewsTools()],12 instructions="You are a tech journalist. Keep summaries brief and facts straight.",13 markdown=True,14)1516# Run and stream the output directly to the terminal! π17agent.print_response("What are the trending startups today?", stream=True)π Running Your Agent
During development, Agent.print_response() is your best friend. It formats the markdown beautifully and prints it directly to your terminal.
For production or custom interfaces, use Agent.run() or Agent.arun() (the async version) to retrieve the structured stream:
1from typing import Iterator2from kern.agent import Agent, RunOutputEvent, RunEvent3from kern.models.openai import OpenAIChat4from kern.tools.hackernews import HackerNewsTools56agent = Agent(7 model=OpenAIChat(id="llama3.2:3b", base_url="http://localhost:11434/v1"),8 tools=[HackerNewsTools()],9 instructions="Write a report on the topic. Output only the report.",10 markdown=True,11)1213# Stream the event outputs14stream: Iterator[RunOutputEvent] = agent.run("Trending tech news", stream=True)15for chunk in stream:16 if chunk.event == RunEvent.run_content:17 print(chunk.content, end="", flush=True)π‘ Dynamic Tools (Callable Factories)
What if you don't want the exact same tools for every session? For example, admins should get file editing access, while standard users only get web search.
Instead of passing a static list, pass a callable function! Kern calls this function at the start of each run, allowing you to customize the tools or knowledge based on the user session. π€―
1from kern.agent import Agent2from kern.models.openai import OpenAIChat3from kern.run import RunContext4from kern.tools.duckduckgo import DuckDuckGoTools5from kern.tools.yfinance import YFinanceTools67# Determine tools on the fly βοΈ8def get_tools_for_user(run_context: RunContext):9 role = (run_context.session_state or {}).get("role", "general")10 if role == "finance":11 return [YFinanceTools()]12 return [DuckDuckGoTools()]1314# Wire up the dynamic tool factory15agent = Agent(16 model=OpenAIChat(id="llama3.2:3b", base_url="http://localhost:11434/v1"),17 tools=get_tools_for_user,18)1920# This run gets financial tools π21agent.print_response("AAPL stock price?", session_state={"role": "finance"}, stream=True)2223# This run gets general web search π24agent.print_response("Latest AI news?", session_state={"role": "general"}, stream=True)βοΈ Callable Caching Settings
Factory results are cached by default. The cache key is resolved in this order: custom key function > user_id > session_id. If none are available, caching is skipped and the factory runs every time.
| Setting | Default | Description |
|---|---|---|
cache_callables | True | Enable or disable caching for all callable factories |
callable_tools_cache_key | None | Custom cache key function for tools factory |
callable_knowledge_cache_key | None | Custom cache key function for knowledge factory |
callable_members_cache_key | None | Custom cache key function for members factory (Team only) |
Set cache_callables=False when session_state changes between runs and the factory should re-evaluate each time.
Clear cached results programmatically:
1from kern.utils.callables import clear_callable_cache23clear_callable_cache(team) # Clear all caches4clear_callable_cache(team, kind="tools") # Clear tools cache only5clear_callable_cache(team, kind="tools", close=True) # Clear and call .close() on cached resourcesUse aclear_callable_cache() in async code.
πΊοΈ Next Steps
Ready to upgrade your agent's capabilities? Explore the guides below:
| What do you want to add? | Where to go next |
|---|---|
| Execution | Running agents π |
| Troubleshooting | Debugging agents π |
| Persistence | Agent sessions πΎ |
| Output Formats | Input and output π |
| Extra Abilities | Custom & Pre-built Tools π οΈ |
| Context Control | Context engineering π§ |
| Files & Media | Multimodal inputs πΌοΈ |
| Safety Net | Guardrails π‘οΈ |