a neighborhood LLM. Good.
However after the primary few chats, you may be questioning: what else can I do with it?
Effectively, how about making the native LLM agentic with some device use?
On this publish, we’ll discover the best way to flip a neighborhood LLM right into a tool-using agent. Particularly, we’ll use
- Gemma 4 mannequin (edge-friendly variants) as our native LLM
- Ollama for serving the native LLM
- OpenAI Brokers SDK for the agent runtime
- Tavily internet search MCP as one instance of the exterior device
We’ll construct a mini deep analysis agent that may search the online, collect the proof, and synthesize a solution with citations, given a person query.
By the top of the publish, you’d have a working native deep analysis agent and a reusable implementation sample for turning a neighborhood mannequin into a neighborhood AI agent.

If you’re considering a neighborhood coding-agent setup, I beforehand coated Gemma 4 + OpenCode. On this publish, we give attention to the extra basic sample of connecting a neighborhood mannequin to an agent runtime and exterior instruments.
1. Set Up the Native Agent Stack
We have to put together 4 items earlier than we write the code: Ollama, Gemma 4 (particularly the Gemma 4 E4B mannequin), OpenAI Brokers SDK, and Tavily MCP.
First, let’s set up Ollama.
On Home windows, you’ll be able to obtain the installer from the official Ollama web site:
https://ollama.com/obtain
Or use winget in PowerShell:
winget set up Ollama.Ollama
On Linux, Ollama will be put in with:
"curl -fsSL https://ollama.com/set up.sh | sh"
After set up, please verify:
ollama --version
On Home windows, keep in mind to launch Ollama from the Begin menu. As soon as it’s working, the native API endpoint is obtainable.
Subsequent, we pull the native mannequin. Right here, we use Gemma 4 E4B variant:
ollama pull gemma4:e4b
Gemma 4 has a number of variants. The E4B mannequin is an efficient match for our objective, as it’s designed with edge/native agentic workflows in thoughts. My machine has an NVIDIA RTX 2000 Ada Laptop computer GPU with about 8 GB VRAM. In case your machine is extra constrained, you’ll be able to attempt the lighter E2B variant:
ollama pull gemma4:e2b
Subsequent, we’d like the agent runtime library. For that, we use OpenAI Brokers SDK:
pip set up openai-agents
You’d additionally want the OpenAI-compatible consumer:
pip set up openai
One thing to notice right here: later, we’ll level the consumer to Ollama’s native endpoint, so this doesn’t imply we’re sending mannequin calls to OpenAI.
Lastly, we’d like a Tavily MCP endpoint. In case you haven’t used it earlier than, Tavily is a search API designed for LLM purposes. On this publish, we use its MCP server so the agent can search the online.
You’d have to first create a Tavily account and get an API key. On the Tavily platform, you’ll be able to instantly generate a MCP hyperlink with the next form:
https://mcp.tavily.com/mcp/?tavilyApiKey=
Now we’re prepared.
Utilizing Tavily right here will not be a sponsored selection; it’s used right here as one handy MCP device, the identical sample can work with different MCP-compatible instruments as nicely.
The truth is, the entire stack right here will not be the one possibility. As an alternative of utilizing Ollama, you might serve the native mannequin with LM Studio or llama.cpp. As an alternative of Gemma 4 fashions, you can even attempt with different fashions from, e.g., Qwen household. For agent framework, we even have choices from Google or Anthropic. You can additionally join totally different MCP instruments as a substitute of Tavily. I exploit this mix just because I’m aware of that stack. However the necessary takeaway on this case research is the overall native agentic sample.
2. Configure the Native Analysis Agent
With OpenAI Brokers SDK, that is the ultimate Agent object we have to compose:
from brokers import Agent
agent = Agent(
identify="Native Analysis Agent",
directions=RESEARCH_AGENT_INSTRUCTIONS,
mannequin=mannequin,
mcp_servers=[tavily_server],
mcp_config={"include_server_in_tool_names": True},
)
Let’s unpack every half.
2.1 The Mannequin
First, the mannequin.
from openai import AsyncOpenAI
from brokers import OpenAIChatCompletionsModel
MODEL_NAME = "gemma4:e4b"
OLLAMA_BASE_URL = "http://localhost:11434/v1"
consumer = AsyncOpenAI(
api_key="ollama",
base_url=OLLAMA_BASE_URL,
)
mannequin = OpenAIChatCompletionsModel(
mannequin=MODEL_NAME,
openai_client=consumer,
)
We begin by making a consumer that factors at Ollama’s native OpenAI-compatible endpoint.
Then, we use OpenAIChatCompletionsModel to wrap the Gemma mannequin right into a mannequin object. This permits the Brokers SDK to make use of that mannequin contained in the agent loop.
Word that the api_key="ollama" worth is only a placeholder. Ollama doesn’t really want an actual OpenAI API key. We use it as a result of the consumer expects this subject.
2.2 The Instruction
Subsequent, we outline the instruction for the agent with the specified analysis conduct:
from datetime import datetime
CURRENT_DATE = datetime.now().strftime("%B %d, %Y")
# Word that this instruction is iterated with AI
RESEARCH_AGENT_INSTRUCTIONS = f"""
[Role]
You're a concise analysis assistant.
[Task]
Reply the person's query by turning it right into a small internet analysis job.
Use the present date when deciphering time-sensitive questions: {CURRENT_DATE}.
[Research behavior]
Begin with one focused search question.
For advice or comparability questions, full this analysis loop earlier than answering:
first determine the primary choices, then seek for comparability context, then synthesize a advice.
Use follow-up searches when the primary outcomes are inadequate, conflicting, or solely cowl a part of the query.
Desire related and credible sources, and monitor which supply helps every necessary declare.
Earlier than answering, verify whether or not the gathered proof is sufficient to assist the conclusion.
[Expected output]
Give a direct reply first, then briefly clarify the proof behind it.
Embody supply hyperlinks for key factual claims.
[Rules]
Don't depend on reminiscence for info that will have modified.
Don't invent lacking particulars.
Preserve the reply concise.
""".strip()
2.3 The Instruments
Now we equip the agent with the online search device. On this case, we use the Tavily search engine by way of MCP:
from brokers import Agent, Runner
from brokers.mcp import MCPServerStreamableHttp
TAVILY_MCP_URL = "YOUR_TAVILY_MCP_URL"
async with MCPServerStreamableHttp(
identify="tavily",
params={"url": TAVILY_MCP_URL},
) as tavily_server:
instruments = await tavily_server.list_tools()
print("Out there Tavily instruments:")
for device in instruments:
description = (device.description or "").substitute("n", " ")
print(f"- {device.identify}: {description[:120]}")
agent = Agent(
identify="Native Analysis Agent",
directions=RESEARCH_AGENT_INSTRUCTIONS,
mannequin=mannequin,
mcp_servers=[tavily_server],
mcp_config={"include_server_in_tool_names": True},
)
outcome = await Runner.run(agent, RESEARCH_QUESTION, max_turns=MAX_TURNS)
This code block does three issues:
- It opens a connection to Tavily’s MCP server with
async with MCPServerStreamableHttp(...) as tavily_server:As soon as linked, Tavily would expose its out there instruments to the Brokers SDK. - We create the Agent object contained in the MCP context. Word that we’ve
mcp_servers=[tavily_server], which attaches Tavily’s MCP instruments to the agent. - We lastly run the agent with
outcome = await Runner.run(agent, RESEARCH_QUESTION, max_turns=MAX_TURNS). The context supervisor issues right here as a result of the MCP connection is just energetic contained in theasync withblock.
mcp_config={"include_server_in_tool_names": True}is especially for readability within the hint. With out it, the device identify will solely seem astavily_search. With it, the device identify will present asmcp_tavily__tavily_search. This makes it clearer that the device name got here by way of the Tavily MCP server.
3. Run a Analysis Query
Now that the agent is configured, let’s check it with one concrete query:
“Which June 23, 2026 World Cup match had the most important group-stage stakes, and why?”
To examine what occurred, I print a compact hint:
def compact(worth: object, restrict: int = 220) -> str:
textual content = str(worth).substitute("n", " ")
return textual content if len(textual content) <= restrict else textual content[:limit] + "..."
for step, merchandise in enumerate(outcome.new_items, begin=1):
raw_item = getattr(merchandise, "raw_item", None)
raw_type = getattr(raw_item, "sort", "")
raw_name = getattr(raw_item, "identify", "")
raw_output = getattr(raw_item, "output", "")
print(
f"{step:02d} | {sort(merchandise).__name__} | "
f"{raw_type or raw_name} | {compact(raw_output or raw_item)}"
)
In my run, the hint seemed like this:
01 | ToolCallItem | function_call | ResponseFunctionToolCall(arguments='{"question":"World Cup 2026 group stage matches June 23, 2026 stakes"}', identify='mcp_tavily__tavily_search', ...)
02 | ToolCallOutputItem | | {'call_id': ..., 'output': ...}
03 | MessageOutputItem | message | ResponseOutputMessage(... closing reply ...)
This permits us to see the agentic conduct instantly. On this run, the native Gemma mannequin determined to name the Tavily search device, the Brokers SDK executed that device name, and handed the outcomes again to the mannequin. Then, the mannequin produced the ultimate reply.
To see the ultimate response, we are able to print:
print(outcome.final_output)
That is what the agent produced:
The match with the most important group-stage stakes on June 23, 2026, was Colombia vs. DR Congo.
Why:
Based on FIFA reporting, this particular match was highlighted as a crucial second the place Colombia superior into the knockout section of the event.
The article notes that Daniel Munoz scored the primary aim for Colombia throughout this Group Ok fixture, which instantly contributed to their development within the competitors.
Proof
- FIFA: An article titled "Colombia v Congo DR Group Ok FIFA World Cup 2026" particularly stories on a key second from this match, stating that Munoz's aim helped fireplace Colombia into the knockout section.
Supply: https://digitalhub.fifa.com/remodel/450614d3-72d7-4c1f-85ff-ea0fbee6f28d/Colombia-v-Congo-DR-Group-Ok-FIFA-World-Cup-2026?focuspoint=0.51
- Yahoo Sports activities: Confirms the fixture and outcome for that date: Colombia defeated DR Congo.
Supply: https://sports activities.yahoo.com/soccer/article/2026-world-cup-results-standings-and-schedule-live-scores-group-stage-updates-and-how-to-watch-050724193.html
Discover that the agent solely made one search spherical on this run, because the search outcomes already contained sufficient proof for the mannequin to reply. For extra advanced questions, a number of rounds of search and reasoning could be mandatory, and our present framework naturally helps that.
4. Wrapping Up
A neighborhood LLM doesn’t have to remain as a chat mannequin.
On this publish, we deployed a Gemma 4 E4B mannequin domestically by way of Ollama, then we put the mannequin inside an agent runtime offered by OpenAI Brokers SDK, and we gave the agent an online search device in order that it will probably discover info on-line to reply customers’ questions.
From right here, you’ll be able to simply lengthen this sample with stronger analysis directions or construct a extra specific planning-reflection workflow, if you wish to hold working within the course of deep analysis, or you’ll be able to join the agent to extra MCP instruments for a lot of different use instances.
Completely happy constructing!
Reference
Ollama: https://ollama.com/
Gemma mannequin household: https://ai.google.dev/gemma
OpenAI Brokers SDK: https://openai.github.io/openai-agents-python/
Brokers SDK MCP docs: https://openai.github.io/openai-agents-python/mcp/
Tavily MCP docs: https://docs.tavily.com/documentation/mcp

