AgentGen + OpenAI Function Calling
OpenAI's function calling (tool calling) lets GPT-4o decide when to invoke external APIs. Define AgentGen's PDF and image endpoints as tools, and your GPT-4o agent will produce downloadable documents as a natural part of any conversation.
Install
pip install openai requests python-dotenv
Step 1 — Define the tool schemas
tools = [
{
"type": "function",
"function": {
"name": "generate_pdf",
"description": (
"Render an HTML document to a PDF and return a CDN download URL. "
"Cost: 2 tokens per page. Use for invoices, reports, certificates."
),
"parameters": {
"type": "object",
"properties": {
"html": {
"type": "string",
"description": "Complete HTML document to render as PDF",
},
"page_size": {
"type": "string",
"enum": ["A4", "Letter", "A3", "Legal"],
"default": "A4",
},
"page_size_source": {
"type": "string",
"enum": ["css", "format"],
"default": "css",
},
},
"required": ["html"],
},
},
},
{
"type": "function",
"function": {
"name": "generate_image",
"description": (
"Render HTML to a PNG, JPEG, or WebP image and return a CDN URL. "
"Cost: 1 token. Use for OG images, thumbnails, screenshots."
),
"parameters": {
"type": "object",
"properties": {
"html": {"type": "string", "description": "HTML to render as image"},
"viewport_width": {"type": "integer", "default": 1200},
"viewport_height": {"type": "integer", "default": 800},
"selector": {"type": "string"},
"format": {"type": "string", "enum": ["png", "jpeg", "webp"], "default": "png"},
},
"required": ["html"],
},
},
},
]Step 2 — Implement the tool handlers
import os, json, requests
AGENTGEN_KEY = os.environ["AGENTGEN_API_KEY"]
def handle_tool_call(name: str, arguments: str) -> str:
args = json.loads(arguments)
if name == "generate_pdf":
r = requests.post(
"https://www.agent-gen.com/api/v1/generate/pdf",
headers={"X-API-Key": AGENTGEN_KEY, "Content-Type": "application/json"},
json={
"html": args["html"],
"page_size_source": args.get("page_size_source", "css"),
"format": args.get("format", "A4"),
},
timeout=30,
)
elif name == "generate_image":
r = requests.post(
"https://www.agent-gen.com/api/v1/generate/image",
headers={"X-API-Key": AGENTGEN_KEY, "Content-Type": "application/json"},
json={
"html": args["html"],
"viewport_width": args.get("viewport_width", 1200),
"viewport_height": args.get("viewport_height", 800),
"selector": args.get("selector"),
"format": args.get("format", "png"),
},
timeout=30,
)
else:
return json.dumps({"error": f"Unknown tool: {name}"})
if r.status_code == 402:
return json.dumps({"error": "Insufficient tokens. Visit agent-gen.com/pricing."})
r.raise_for_status()
return json.dumps(r.json())Step 3 — The agent loop
from openai import OpenAI
client = OpenAI()
def run_agent(user_message: str) -> str:
messages = [
{
"role": "system",
"content": (
"You are a helpful assistant that can generate PDFs and images. "
"When a user asks for a document or image, write clean HTML with "
"inline styles and call the appropriate tool."
),
},
{"role": "user", "content": user_message},
]
while True:
response = client.chat.completions.create(
model="gpt-4o",
messages=messages,
tools=tools,
tool_choice="auto",
)
msg = response.choices[0].message
if msg.tool_calls:
messages.append(msg)
for call in msg.tool_calls:
result = handle_tool_call(call.function.name, call.function.arguments)
messages.append({
"role": "tool",
"tool_call_id": call.id,
"content": result,
})
else:
return msg.content
# Run it
print(run_agent("Create a PDF invoice for Acme Corp, $3,500 for API development, due April 1"))
# → "Here's your invoice: https://cdn.agent-gen.com/output/abc123.pdf"Using with the Assistants API
The same tool definitions work with the OpenAI Assistants API. Create an Assistant with the tools array above, then handle requires_action run statuses the same way:
assistant = client.beta.assistants.create(
name="Document Generator",
instructions="Generate professional PDFs and images using the provided tools.",
model="gpt-4o",
tools=tools,
)
thread = client.beta.threads.create()
client.beta.threads.messages.create(thread.id, role="user",
content="Generate a certificate PDF for Alice Smith, Python course, March 2026")
run = client.beta.threads.runs.create_and_poll(
thread_id=thread.id,
assistant_id=assistant.id,
)
if run.status == "requires_action":
tool_outputs = []
for call in run.required_action.submit_tool_outputs.tool_calls:
output = handle_tool_call(call.function.name, call.function.arguments)
tool_outputs.append({"tool_call_id": call.id, "output": output})
run = client.beta.threads.runs.submit_tool_outputs_and_poll(
thread_id=thread.id, run_id=run.id, tool_outputs=tool_outputs,
)When to prefer OpenAI tools
This setup is strongest when your product already runs on OpenAI chat or Assistants APIs and you want the model itself to decide when to produce a formal artifact such as an invoice, certificate, receipt, or report.
The practical benefit is that the tool result is already structured JSON with a hosted file URL. That removes one more translation step between model output and user-facing deliverable.
Operational guidance
- Keep tool descriptions precise so the model distinguishes between PDF and image generation reliably.
- Cap HTML size and validate required fields before sending the request to avoid wasted completions.
- Persist the returned URL if downstream systems need to display or share the generated asset later.
Give your GPT-4o agent document generation
50 free tokens on signup. No credit card required.