A useful resume tool should let you see where each suggested claim came from. If it changes “helped maintain a spreadsheet” into “led a data transformation,” the polished wording has made the resume less accurate.
This tutorial builds a small local Python prototype: a review queue for proposed resume bullets and a SQLite job-application tracker. All example data is synthetic. You can use an assistant to propose wording, then pass that wording into the review queue. The code does not call a model, send a resume, or submit an application.
Start with source facts
Give each fact an identifier. Preserve the original wording so the person reviewing the suggestion can compare it directly. Our example has two facts about a student-club equipment inventory.
Use a request like this with your chosen assistant:
Suggest a resume bullet using only these facts: f1: Maintained the equipment inventory for a student club. f2: Used a spreadsheet to record equipment checkouts. Return a JSON array of objects with text and fact_ids. Preserve the level of responsibility. Do not add results, quantities, skills, or credentials absent from these facts. Flag missing information separately.
Treat the response as proposed text. The fixture below was prepared for this example; it is not presented as output from a measured AI run.
Save the prototype
Save the following as resume_tracker.py. It uses Python's standard library, so there is no package installation step.
"""Local teaching example. Synthetic data; no model call or application submission."""
import sqlite3
FACTS = {"f1": "Maintained the equipment inventory for a student club.",
"f2": "Used a spreadsheet to record equipment checkouts."}
def review_queue(suggestions):
queue = []
for item in suggestions:
refs = item.get("fact_ids")
text = item.get("text")
if not isinstance(text, str) or not text.strip():
raise ValueError("Suggestion text is required")
if not isinstance(refs, list) or not refs or any(
not isinstance(ref, str) or ref not in FACTS for ref in refs
):
raise ValueError("Every suggestion needs known source fact IDs")
queue.append({"text": text.strip(), "sources": [FACTS[r] for r in refs],
"status": "needs_human_review"})
return queue
def save_application(path, application_id, company, role, status):
if status not in {"saved", "applied", "interview", "closed"}:
raise ValueError("Unsupported application status")
if any(not isinstance(v, str) or not v.strip()
for v in [application_id, company, role]):
raise ValueError("Application ID, company and role are required")
with sqlite3.connect(path) as db:
db.execute("CREATE TABLE IF NOT EXISTS applications "
"(id TEXT PRIMARY KEY, company TEXT, role TEXT, status TEXT)")
db.execute("INSERT INTO applications VALUES (?, ?, ?, ?) "
"ON CONFLICT(id) DO UPDATE SET company=excluded.company, "
"role=excluded.role, status=excluded.status",
(application_id.strip(), company.strip(), role.strip(), status))
def list_applications(path):
with sqlite3.connect(path) as db:
return db.execute("SELECT id, company, role, status "
"FROM applications ORDER BY id").fetchall()
if __name__ == "__main__":
import json
print(json.dumps(review_queue([{
"text": "Tracked student-club equipment checkouts in a spreadsheet.",
"fact_ids": ["f1", "f2"]}]), indent=2))
save_application("applications.sqlite", "demo-1", "Example Studio", "Coordinator", "saved")
print(list_applications("applications.sqlite"))
Run it from a folder where you want the local database saved:
python3 resume_tracker.py
The output contains the suggested bullet, both original facts, and needs_human_review. It also shows a saved application for the fictional Example Studio. Running the script again updates the same demo-1 record instead of creating another copy.
To record a later stage, call save_application with the same ID and a supported status such as interview. That label records your own update; it does not contact an employer or verify that an interview exists.
Compare suggested wording with the source facts
The reference check rejects missing and unknown fact IDs. It cannot determine whether the proposed sentence is supported by those facts. A fabricated claim can cite f1 and still enter the queue. The reviewer must compare the wording with the visible sources before using it.
The prototype also leaves model-response parsing to the caller: pass a Python list of dictionaries after checking the response format. A deployed interface would need input-size limits, validation for malformed responses, user accounts, access checks, and a deliberate retention policy for personal information.
The local checks for this walkthrough exercised source visibility, missing references, blank text, persistence, repeated updates, and invalid status rejection. Fabricated wording with a valid reference remained unapproved in the test. No live model quality test or hosted application test was performed.
Use the queue to make an actual review decision
The synthetic sentence “Tracked student-club equipment checkouts in a spreadsheet” stays close to the supplied facts. A reviewer can compare the activity, context, and tool directly. The sentence “Led a team that eliminated inventory losses” adds leadership and an outcome that neither fact supplies. Referencing both fact IDs would not repair that mismatch.
If the assistant proposes the second sentence, reject it or revise it to the supported activity. If the applicant really did lead a team, add an accurate source fact before requesting another suggestion. Keeping the source record current is preferable to asking the model to infer missing achievements.
The tracker has a different job. Its stable application ID lets you update an existing entry even when two roles share the same company name. The status is manually recorded. The prototype stores only the latest status; a richer version would need separate history if you want to reconstruct when stages changed.
This implementation also keeps review items in memory. It does not save an approval decision or produce a formatted resume. Those are explicit next features: persist the source, proposed text, reviewer decision, and final wording together, then render only the wording the person approved.
Turn the prototype into a web application
For an OBTO implementation, use a separate app with a review screen, a server-side data layer, and application records scoped to the signed-in user. Keep source facts, suggestions, and approval decisions separately so an edit does not erase its provenance. Use the OBTO connection guide to connect the agent to the intended application.
Before adding real resumes, test that one account cannot read another account's records. Keep the human review step visible beside the suggested text, including after a page reload.