By Markus van Kempen |
Series: WXO Labs & Tutorial Guide (Part 6 of 15)
Interactive Lab Portal: https://markusvankempen.github.io/wxo-labs/
GitHub Repository: https://github.com/markusvankempen/wxo-labs
Executives often require formal PDF briefing packets with corporate headers and timestamps. Rather than sending static templates, our agent synthesizes live conversational data and renders a downloadable binary PDF on demand.
Ensure your environment has the required dependencies:
pip install ibm-watsonx-orchestrate
Verify active environment:
orchestrate env list
pdf_generator.py)from ibm_watsonx_orchestrate import tool
from reportlab.lib.pagesizes import letter
from reportlab.pdfgen import canvas
import tempfile
import os
from datetime import datetime
@tool
def generate_report_pdf(report_title: str, report_body: str) -> str:
"""
Generate a formatted binary PDF document and return a download URI.
"""
temp_dir = tempfile.gettempdir()
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
filename = f"WXO_Report_{timestamp}.pdf"
filepath = os.path.join(temp_dir, filename)
c = canvas.Canvas(filepath, pagesize=letter)
width, height = letter
# Header branding
c.setFont("Helvetica-Bold", 18)
c.setFillColorRGB(0.06, 0.38, 0.99) # IBM Blue
c.drawString(50, height - 50, "IBM watsonx Orchestrate")
c.setFont("Helvetica-Bold", 14)
c.setFillColorRGB(0.1, 0.1, 0.1)
c.drawString(50, height - 85, report_title)
c.setFont("Helvetica", 9)
c.setFillColorRGB(0.4, 0.4, 0.4)
c.drawString(50, height - 105, f"Generated: {datetime.now().strftime('%B %d, %Y at %H:%M:%S UTC')}")
# Body
c.setFont("Helvetica", 11)
c.setFillColorRGB(0.1, 0.1, 0.1)
text_object = c.beginText(50, height - 140)
for line in report_body.split("\n"):
text_object.textLine(line)
c.drawText(text_object)
c.save()
filesize = os.path.getsize(filepath)
return f"""
📄 PDF Document Generated Successfully
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Title: {report_title}
File: {filename} ({filesize:,} bytes)
Location: {filepath}
Status: Ready for download
"""
requirements.txt)ibm-watsonx-orchestrate>=2.9.0
reportlab>=4.0.0
agent.yaml)spec_version: v1
kind: native
name: report_publisher_agent
title: "Report Publisher"
description: "Generates formatted PDF executive briefings on demand."
model: ibm/granite-3-8b-instruct
instructions: |
You are an executive publishing assistant. Format summaries into structured
briefings and call `generate_report_pdf` to create the document.
tools:
- generate_report_pdf
Import tool and test conversationally:
orchestrate chat ask -n report_publisher_agent "Generate a PDF report on Q3 AI Adoption"
Live Response:
╭─ 🤖 report_publisher_agent ───────────────────────────────────────────╮
│ │
│ 📄 PDF Document Generated Successfully │
│ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ │
│ Title: Q3 AI Adoption Briefing │
│ File: WXO_Report_20260924_201500.pdf (4,812 bytes) │
│ Status: Ready for download │
╰────────────────────────────────────────────────────────────────────────╯
When publishing this blog post, select or enter the following tags in the community editor:
watsonx Orchestrate, PDF Generation, File Streaming, ReportLab, AI Documents, Python
This tutorial is Part 6 of 15 in the complete enterprise hands-on series:
Explore the interactive curriculum and code repository: