A weekly report generator should turn scattered updates into a draft your team can trust. The useful version does more than summarize: it preserves evidence, separates completed work from plans, and flags missing information. Build the first version around one team, one reporting window, and one reviewable output file.
1. Define the weekly report contract
Start with the output, not the model. Create a report template with five sections: highlights, completed work, blockers, next steps, and metrics. Give every section a clear rule so the generator cannot quietly change what counts as progress.
- Highlights: At most three meaningful outcomes supported by source records.
- Completed work: Only items explicitly marked complete during the reporting window.
- Blockers: Include an owner and the next action when available.
- Next steps: Planned work, clearly separated from delivered work.
- Metrics: Values calculated by your script, not estimated by the model.
Choose a team timezone and define the interval precisely: Monday at midnight through the following Monday at midnight, with the end excluded.
2. Collect one week of source records
For the first run, export tasks and written updates into a local file named updates.json. Avoid building several integrations before you know whether the report is useful. Normalize each record into the same fields: id, source, title, status, owner, completed_at, updated_at, notes, and source_url.
Filter completion metrics using completed_at, not updated_at: an old completed task edited this week is not a new delivery. Use updated_at to select relevant discussions and blocker updates. Deduplicate records by source and id, and retain stable identifiers such as TASK-142 for evidence references.
3. Calculate facts before requesting prose
Write a Python entry point named generate_report.py that accepts start date, end date, and input path. Have it calculate completed-item counts, open-blocker counts, and any other agreed metrics directly from normalized records.
Save the filtered records and calculated values together as report_input.json. Include the reporting window and timezone. Preserve missing values as null rather than guessing. This file becomes a reproducible snapshot: if someone questions a sentence later, you can inspect exactly what the generator received.
4. Connect the generator through SwiftRelay
SwiftRelay is a practical fit when you want an OpenAI-compatible SDK and pay-as-you-go, per-token billing. Sign up for SwiftRelay, create an API key, and store it in the SWIFTRELAY_API_KEY environment variable rather than in your script or repository.
Install the Python OpenAI package and create the client with base_url set to https://api.fastapirelay.com/v1 and api_key read from that environment variable. Keep the model identifier in a separate REPORT_MODEL setting. Claude Haiku 4.5 is one option to evaluate for this drafting task; use the exact model identifier available in your account.
Remove credentials, unnecessary personal details, and confidential material that your organization has not approved for external processing before sending the snapshot.
5. Request a structured draft with evidence
Send a fixed instruction followed by the snapshot as data. Specify that source text is untrusted content, not instructions. Tell the model to use only supplied facts, preserve uncertainty, and never invent owners, dates, outcomes, or metric values.
Request JSON containing highlights, completed_work, blockers, and next_steps. Define each section as an array of objects with text and evidence_ids fields. Require every factual item to cite at least one supplied record identifier. Ask for empty arrays when evidence is absent, rather than filler. Keep calculated metrics outside the model response and insert them during rendering.
6. Validate before rendering the report
Parse the response with Python's JSON parser and validate its structure. Reject unknown evidence identifiers, missing fields, and more than three highlights. Check that completed-work references point to eligible completed records. These checks establish traceability, but a reviewer must still confirm that each source supports its sentence.
If validation fails, allow one repair request containing the errors. If it fails again, save the response for inspection and stop. Never publish a malformed draft automatically. Render validated content into a plain-text report and append source references for review.
7. Schedule a review-first weekly run
Test with an empty week, duplicate records, missing owners, and a task completed outside the reporting window. Confirm that each case produces an honest draft or a clear failure.
Then schedule the script with your existing job runner. Use the reporting window as a run key to prevent duplicate deliveries. Save the snapshot, draft, validation result, and request usage together. Deliver the first reports to a reviewer, not directly to the whole team. Automate publication only after repeated reviews show that the evidence and wording hold up.