We are going to build a meeting-prep agent that researches a prospect and drafts a one-page briefing. It uses function calling to fetch simulated company data and recent news, then synthesizes the results into a concise markdown report. If you run sales or consulting, this eliminates the repetitive pre-call research.
What you'll need
- Python 3.10 or newer
- The OpenAI SDK:
pip install openai - An Oxlo.ai API key from https://portal.oxlo.ai
Step 1: Set up the Oxlo.ai client
Oxlo.ai exposes an OpenAI-compatible API, so we can use the official SDK with only a base URL change. I will instantiate the client once and reuse it.
from openai import OpenAI
client = OpenAI(base_url="https://api.oxlo.ai/v1", api_key="YOUR_OXLO_API_KEY")
Step 2: Define the tools
The agent needs two capabilities: looking up a company profile and fetching recent news. I will mock both with static JSON so the script runs without extra API keys. I also need to declare the JSON schemas so the model knows how to call them.
import json
def get_company_profile(company_name: str) -> str:
"""Return a mock company profile."""
return json.dumps({
"name": company_name,
"industry": "Enterprise Software",
"employees": 1200,
"headquarters": "San Francisco, CA",
"revenue_band": "$50M-$100M",
"key_products": ["Cloud CRM", "Analytics Dashboard"]
})
def get_recent_news(company_name: str) -> str:
"""Return mock recent news items."""
return json.dumps([
{"date": "2025-06-10", "headline": f"{company_name} launches AI assistant"},
{"date": "2025-06-05", "headline": f"{company_name} raises Series C"}
])
TOOLS = [
{
"type": "function",
"function": {
"name": "get_company_profile",
"description": "Fetch basic company info such as industry, size, and products.",
"parameters": {
"type": "object",
"properties": {
"company_name": {"type": "string", "description": "The company name"}
},
"required": ["company_name"]
}
}
},
{
"type": "function",
"function": {
"name": "get_recent_news",
"description": "Fetch recent news headlines for a company.",
"parameters": {
"type": "object",
"properties": {
"company_name": {"type": "string", "description": "The company name"}
},
"required": ["company_name"]
}
}
}
]
Step 3: Write the system prompt
The system prompt is the agent's job description. It instructs the model to call tools when needed and to output a strict markdown briefing.
SYSTEM_PROMPT = """You are a meeting-prep assistant. Your job is to research a prospect and produce a concise, one-page markdown briefing.
Follow these rules:
1. Always call the available tools to gather facts. Do not invent data.
2. After you receive tool results, synthesize them into a markdown report.
3. Use this structure:
- Overview
- Key Products / Services
- Recent News
- Conversation Starters
4. Keep the total output under 200 words.
5. Do not mention that you used tools."""
Step 4: Build the agent loop
We need a loop that sends the user request to the model, handles any tool calls, and then asks the model to generate the final answer with the tool results. I use Oxlo.ai's kimi-k2.6 because it handles agentic tool use and long context well, but you can swap in qwen-3-32b or deepseek-v3.2 without changing any other code.
def run_agent(company_name: str) -> str:
messages = [
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": f"Prepare a briefing for {company_name}"}
]
# First call: let the model decide which tools to use
response = client.chat.completions.create(
model="kimi-k2.6",
messages=messages,
tools=TOOLS,
tool_choice="auto"
)
assistant_message = response.choices[0].message
messages.append(assistant_message)
# If the model requested tool calls, execute them
if assistant_message.tool_calls:
for tool_call in assistant_message.tool_calls:
func_name = tool_call.function.name
args = json.loads(tool_call.function.arguments)
if func_name == "get_company_profile":
result = get_company_profile(**args)
elif func_name == "get_recent_news":
result = get_recent_news(**args)
else:
result = json.dumps({"error": "unknown tool"})
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"name": func_name,
"content": result
})
# Second call: generate the final briefing with tool results
final_response = client.chat.completions.create(
model="kimi-k2.6",
messages=messages
)
return final_response.choices[0].message.content
# If no tools were called, return the model's direct response
return assistant_message.content
Step 5: Run it
Call the agent with a prospect name and print the result. Because Oxlo.ai charges a flat rate per request, running the two API calls in this loop costs the same per call regardless of how long the tool outputs are. That makes long-context research workflows predictable.
if __name__ == "__main__":
briefing = run_agent("Acme Corp")
print(briefing)
When I ran this, the output looked like this:
## Acme Corp Briefing
**Overview**
Acme Corp is an enterprise software company based in San Francisco with roughly 1,200 employees. It sits in the $50M-$100M revenue band.
**Key Products / Services**
- Cloud CRM
- Analytics Dashboard
**Recent News**
- June 10, 2025: Acme Corp launches AI assistant
- June 5, 2025: Acme Corp raises Series C
**Conversation Starters**
- Ask about the new AI assistant launch and how it integrates with their existing CRM stack.
- Congratulate them on the Series C and explore whether their analytics roadmap is expanding.
Next steps
Swap the mock functions for real APIs such as Crunchbase or a news aggregator, and store the results in a vector database for reuse. You could also trigger this agent from a calendar webhook so every meeting on your schedule is researched automatically.
Top comments (0)