Hello World Agent
One tool, one question, one file — the same agent in every framework.
View as MarkdownEvery example on this page builds the same agent: a get_weather tool wired
to an LLM in a ReAct loop. The LLM reasons about what to do, acts by
calling the tool, observes the result, then returns a final answer.
The same code works with OpenAI, any OpenAI-compatible endpoint (vLLM, Ollama, RHOAI Model-as-a-Service), or a locally hosted model — just change the environment variables. Pick your framework below to jump to a working example.
How it works
Every framework implements the same loop under different abstractions:
- The LLM sees the user message and the list of available tools.
- If the LLM decides it needs information, it emits a tool call (e.g.
get_weather("Portland")). - The framework executes the tool and feeds the result back to the LLM.
- The LLM either calls another tool or returns a final answer.
A tool is any Python function with a docstring. The framework converts it to a function schema automatically — the function name becomes the tool name, the docstring becomes the description, and type hints become the parameter schema.
Running it
Each example reads model connection details from environment variables.
Install the framework's dependencies (shown in the requirements.txt tab),
set the env vars below, and run python agent.py.
OpenAI
export OPENAI_API_KEY="sk-..."Local or hosted model
Any OpenAI-compatible API works — vLLM, Ollama, RHOAI Model-as-a-Service,
LM Studio, or any other server that implements the
/v1/chat/completions endpoint with tool calling support.
# Any OpenAI-compatible endpoint: vLLM, Ollama, RHOAI MaaS, etc.
export OPENAI_BASE_URL="http://maas.apps.my-cluster.example.com/v1"
export OPENAI_MODEL_NAME="gemma4"
export OPENAI_API_KEY="your-token-here"The model must support tool calling (function calling) for the ReAct loop to work. Models known to work: Gemma 4, Llama 4 Scout, Llama 3.1+, Mistral Instruct v0.3+, Qwen 2.5+.
human: What's the weather in Portland?
ai:
tool: The weather in Portland is sunny, 72 F.
ai: The weather in Portland is currently sunny and 72 F.Agent Frameworks
LangGraph
LangGraph provides
create_react_agent — a one-liner that wires tools into the
reason → act → observe loop. It uses ChatOpenAI under the hood, which
reads OPENAI_API_KEY and OPENAI_BASE_URL from the environment
automatically.
"""Hello World ReAct agent — LangGraph."""
import os
from langchain_openai import ChatOpenAI
from langgraph.prebuilt import create_react_agent
def get_weather(city: str) -> str:
"""Get the current weather for a city."""
return f"The weather in {city} is sunny, 72 F."
llm = ChatOpenAI(
model=os.environ.get("OPENAI_MODEL_NAME", "gpt-4o-mini"),
base_url=os.environ.get("OPENAI_BASE_URL"),
api_key=os.environ.get("OPENAI_API_KEY"),
)
agent = create_react_agent(
llm,
tools=[get_weather],
prompt="You are a helpful assistant. When you receive a tool "
"result, summarize it as a final answer.",
)
result = agent.invoke(
{"messages": [{"role": "user", "content": "What's the weather in Portland?"}]}
)
for msg in result["messages"]:
print(f"{msg.type}: {msg.content}")
CrewAI
CrewAI models agents as role-playing team members.
Even for a single agent, you define a role, goal, and backstory. Tools are
decorated with @tool. The LLM wrapper accepts an openai/ model prefix
to target any OpenAI-compatible endpoint.
"""Hello World agent — CrewAI."""
__import__("pysqlite3")
import sys
sys.modules["sqlite3"] = sys.modules.pop("pysqlite3")
import os
from crewai import Agent, Task, Crew, LLM
from crewai.tools import tool
@tool("get_weather")
def get_weather(city: str) -> str:
"""Get the current weather for a city."""
return f"The weather in {city} is sunny, 72 F."
llm = LLM(
model=f"openai/{os.environ.get('OPENAI_MODEL_NAME', 'gpt-4o-mini')}",
base_url=os.environ.get("OPENAI_BASE_URL"),
api_key=os.environ.get("OPENAI_API_KEY"),
)
agent = Agent(
role="Weather Reporter",
goal="Look up weather using the get_weather tool and summarize the result",
backstory="You are a helpful weather assistant. Always use your tools "
"to get data, then write a clear summary as your final answer.",
llm=llm,
tools=[get_weather],
max_iter=5,
max_retry_limit=3,
)
task = Task(
description="What is the weather in Portland? Use the get_weather tool "
"to find out, then respond with a one-sentence summary.",
expected_output="A single sentence like: The weather in Portland is ...",
agent=agent,
)
crew = Crew(agents=[agent], tasks=[task])
result = crew.kickoff()
print(result.raw)
AutoGen
AutoGen uses an async-first design.
An AssistantAgent wraps a model client and a list of tools — call
agent.run() to execute. The OpenAIChatCompletionClient connects to any
OpenAI-compatible endpoint.
"""Hello World agent — AutoGen."""
import os
import asyncio
from autogen_agentchat.agents import AssistantAgent
from autogen_ext.models.openai import OpenAIChatCompletionClient
def get_weather(city: str) -> str:
"""Get the current weather for a city."""
return f"The weather in {city} is sunny, 72 F."
model_name = os.environ.get("OPENAI_MODEL_NAME", "gpt-4o-mini")
model_client = OpenAIChatCompletionClient(
model=model_name,
base_url=os.environ.get("OPENAI_BASE_URL"),
api_key=os.environ.get("OPENAI_API_KEY"),
model_info={
"vision": False,
"function_calling": True,
"json_output": True,
"structured_output": True,
"family": "unknown",
},
)
agent = AssistantAgent(
name="weather_agent",
model_client=model_client,
tools=[get_weather],
)
async def main():
result = await agent.run(task="What's the weather in Portland?")
print(result.messages[-1].content)
asyncio.run(main())
LlamaIndex
LlamaIndex uses AgentWorkflow with an
explicit ReActAgent for text-based tool calling — more reliable than
function calling with non-OpenAI models. Use OpenAILike instead of
OpenAI for custom model names — it accepts any OpenAI-compatible
endpoint via api_base.
"""Hello World ReAct agent — LlamaIndex."""
import os
import asyncio
from llama_index.core.agent.workflow import AgentWorkflow, ReActAgent
from llama_index.core.tools import FunctionTool
from llama_index.llms.openai_like import OpenAILike
def get_weather(city: str) -> str:
"""Get the current weather for a city."""
return f"The weather in {city} is sunny, 72 F."
llm = OpenAILike(
model=os.environ.get("OPENAI_MODEL_NAME", "gpt-4o-mini"),
api_base=os.environ.get("OPENAI_BASE_URL"),
api_key=os.environ.get("OPENAI_API_KEY"),
is_chat_model=True,
is_function_calling_model=False,
context_window=128000,
)
react_agent = ReActAgent(
name="weather_agent",
description="Looks up the weather",
tools=[FunctionTool.from_defaults(fn=get_weather)],
llm=llm,
)
agent = AgentWorkflow(agents=[react_agent], root_agent="weather_agent")
async def main():
response = await agent.run("What's the weather in Portland?")
print(response)
asyncio.run(main())
Google ADK
Google Agent Development Kit builds
agents using Gemini models natively, but supports any OpenAI-compatible
endpoint via its LiteLlm integration. The openai/ model prefix tells
LiteLLM to use the OpenAI chat completions API. Tools are plain Python
functions passed to the Agent constructor.
"""Hello World agent — Google ADK."""
import os
import asyncio
from google.adk.agents import Agent
from google.adk.models.lite_llm import LiteLlm
from google.adk.runners import Runner
from google.adk.sessions import InMemorySessionService
from google.genai import types
def get_weather(city: str) -> str:
"""Get the current weather for a city."""
return f"The weather in {city} is sunny, 72 F."
model = LiteLlm(
model=f"openai/{os.environ.get('OPENAI_MODEL_NAME', 'gpt-4o-mini')}",
api_base=os.environ.get("OPENAI_BASE_URL"),
api_key=os.environ.get("OPENAI_API_KEY"),
)
agent = Agent(
name="weather_agent",
model=model,
description="A helpful weather assistant",
instruction="Help users check the weather. "
"Use the get_weather tool when asked.",
tools=[get_weather],
)
session_service = InMemorySessionService()
runner = Runner(
agent=agent, app_name="weather_app",
session_service=session_service,
)
async def main():
session = await session_service.create_session(
app_name="weather_app", user_id="user1",
)
message = types.Content(
role="user",
parts=[types.Part(text="What's the weather in Portland?")],
)
async for event in runner.run_async(
user_id="user1", session_id=session.id,
new_message=message,
):
if event.is_final_response():
print(event.content.parts[0].text)
asyncio.run(main())
Deploy on OpenShift
You can build and run any of the agents above on OpenShift using a UBI 9
Python 3.12 multi-stage build. The Dockerfile uses S2I assemble to install
dependencies in a builder stage, then copies the virtual environment into a
minimal runtime image.
Build the image
Create the Dockerfile, copy your agent.py and requirements.txt into an
app-src/ folder, create a binary BuildConfig, and start the build:
# Create the Dockerfile
cat <<'EOF' > Dockerfile
# build
FROM registry.access.redhat.com/ubi9/python-312:latest as builder
USER 0
ADD app-src /tmp/src
RUN /usr/bin/fix-permissions /tmp/src
USER 1001
RUN /usr/libexec/s2i/assemble
# deploy
FROM registry.access.redhat.com/ubi9/python-312-minimal:latest
COPY --from=builder /opt/app-root /opt/app-root
USER 1001
CMD ["python", "agent.py"]
EOF
# Copy source files into app-src/
mkdir app-src
cp agent.py app-src/agent.py
cp requirements.txt app-src/requirements.txt
# Create an OpenShift project (you must be logged in)
oc new-project basic-agents
# Create a binary build config
oc -n basic-agents new-build --binary --name=agent
# Start the build and follow the logs
oc -n basic-agents start-build agent --from-dir=. --followExport env vars
Set your model connection details before creating the pod:
export OPENAI_API_KEY=<your-key>
export OPENAI_MODEL_NAME=<your-model>
export OPENAI_BASE_URL=<your-endpoint>Run the agent
Once the build completes, run the agent as a one-shot pod:
oc -n basic-agents run agent \
--restart=Never \
--image=image-registry.openshift-image-registry.svc:5000/basic-agents/agent:latest \
--env OPENAI_API_KEY=$OPENAI_API_KEY \
--env OPENAI_MODEL_NAME=$OPENAI_MODEL_NAME \
--env OPENAI_BASE_URL=$OPENAI_BASE_URLCheck the logs
oc -n basic-agents logs agentClean up
oc -n basic-agents delete bc,is,pod agent