An AI agent for job hunting: a résumé tailored to the job and cover letters
We build a small tool: you give a vacancy text and a file with your real experience, and get a tailored résumé, a letter and a list of gaps. No invented skills.
4 min · · агенты · автоматизация
Applying to jobs with one generic résumé is ineffective, and rewriting the résumé by hand for each posting takes long. You can hand that work to a model if you set firm limits: take facts only from your profile and honestly mark what is missing. Below we build an AI agent for job hunting in Python: a vacancy goes in, a résumé and a cover letter come out, plus a check so that no invented experience gets into the text.
An honest note on the word "agent". What we build is closer to a two-request pipeline than to an autonomous agent that browses sites and mass-sends applications. For this task a pipeline is better: it is predictable, cheap and sends nothing without you. How to tell an agent from a simple script is covered in An AI agent in Python from scratch; here we go straight to the point.
How it works
- Once, you fill in
profile.md: jobs, projects, stack, achievements with numbers, education. Only what is true. - The input is the vacancy text.
- First request: the model extracts the vacancy requirements, matches them against the profile and writes the résumé and the letter. If a requirement is not in the profile, it does not invent it but puts it into a list of gaps.
- Second request: verification. The model lists every claim in the result and looks for its support in the profile.
- You read the result and send it yourself.
The profile: the basis of honesty
The more accurate the profile, the better the result. An example structure:
Candidate profile
## Experience
### Backend developer, Example LLC, 2022-2025
- Maintained an order service in Python/FastAPI, ~40 requests per second at peak
- Moved reports from Excel to PostgreSQL, generation time from 15 minutes to 40 seconds
## Stack
Python, FastAPI, PostgreSQL, Docker, basic Kubernetes
## Education
...Enter the numbers and wording yourself. The rule: if a fact is not in the profile, it will not be in the résumé. Do not put passwords, passport data or contacts that must not reach a third-party service into the profile: add contacts to the final document by hand.
The code
We use the gateway's OpenAI-compatible API: base_url="https://api.zukko.pro/v1", key fetch_.... More about the client in the Python reference.
import json
import sys
from openai import OpenAI
client = OpenAI(base_url="https://api.zukko.pro/v1", api_key="fetch_...")
MODEL = "claude-sonnet-5-5"
PROFILE = open("profile.md", encoding="utf-8").read()
GEN_RULES = """You help prepare a job application.
Rules:
1. Use only facts from the profile. Add nothing: no skills, numbers or companies.
2. If a vacancy requirement is not backed by the profile, do not claim it. Put it into gaps.
3. Résumé: 5-7 experience points, rephrased in the vacancy's language.Run it with python job_agent.py vacancy.txt. The response_format={"type": "json_object"} mode asks the model to return JSON; if you need a strict schema, see Structured JSON output. Check how this parameter behaves with your model on a test request; if you get a 400 error, drop response_format and keep the JSON requirement in the prompt.
How to avoid invented experience
An invented skill in a résumé surfaces at the first technical interview. Protection is built in several layers:
- A firm rule in the prompt and a separate
gapslist: the model is given "permission" to admit that something is missing. - A second verification pass, as in the code above. The reviewer gets the same facts and is asked to look for discrepancies, not to write the text again.
- Your own reading. Automatic checking does not replace your eyes: go through every number and date.
- Wording without exaggeration. Ask not to strengthen verbs: "took part in" must not turn into "led".
The gaps list is useful in itself: it is what the vacancy asks for and your profile lacks. Either you add the missing fact (if it is true) or you decide the vacancy does not suit you.
What it costs
Let us estimate one application with illustrative volumes. The first request input: instructions, profile and vacancy, about 3000 tokens. Output: résumé, letter and gaps, about 1200 tokens. Verification: input about 4200 tokens (profile and result), output about 300.
Prices as of October 18, 2026, $ per 1M tokens:
claude-sonnet-5-5 (0.4 / 2):
generation: 3000 × 0.4 / 1e6 + 1200 × 2 / 1e6 = 0.0012 + 0.0024 = $0.0036
verification: 4200 × 0.4 / 1e6 + 300 × 2 / 1e6 = 0.00168 + 0.0006 = $0.00228
total per application: $0.00588; for 100 applications about $0.59
deepseek-v4.1-flash (0.013 / 0.038):
generation: 3000 × 0.013 / 1e6 + 1200 × 0.038 / 1e6 ≈ $0.000085
verification: 4200 × 0.013 / 1e6 + 300 × 0.038 / 1e6 ≈ $0.000066
total per application: about $0.00015; for 100 applications about $0.015
The cost per application is negligible in both cases compared with the time spent on manual tailoring. Which to choose only a trial can tell: run three real vacancies on two models and compare the letters. Current prices and the list of models: GET https://api.zukko.pro/v1/models. It will not be "free" here, but spend is measured in cents.
What you can add
- Several versions of the letter in different tones to choose from.
- Interview preparation: ask for a list of questions based on the gaps and your stack.
- Saving results to a spreadsheet to keep track of applications.
- Do not add automatic sending of applications: sending without your control easily leads to inaccurate letters to irrelevant companies.
One more point: a résumé contains personal data. Send the model a depersonalized profile (without phone, address, and employer names if they are sensitive) and add contacts to the finished document.
To start, create a key in the dashboard, fill in profile.md and run the script on one vacancy.
FAQ
Can I build an AI agent for job hunting for free?
Access to models is paid: spend is deducted from the balance per token. But for this task it is very small, fractions of a cent per application. Separately, there is a one-time $0.50 for subscribing to the @zukkopro channel (once per Telegram account); details are in the dashboard.
What if the model still attributes a skill I do not have?
Verification exists for that, and the final word is your own reading. Strengthen the prompt rule ("if unsure, put it into gaps") and compare the result on another model.
Does such a tool need a "real" agent with tools?
For tailoring a résumé, no: two requests are enough. Agent mode with function calls is needed if you want the model to read files or reach external services itself; then see function calling.
How do I find the vacancies themselves?
Copy the vacancy text by hand or from your own collections. Check automatic collection from sites against those sites' rules; we do not describe such a script.
zukko
Pay 25×
less
for Claude Code & ChatGPT
One fetch_* key and base URL api.zukko.pro — for Cursor, Claude Code, Codex, and any SDK.
Related articles
- Skills in Codex: what they are and how to write your ownA Codex skill is a folder with SKILL.md that the agent loads by description or on your call. Structure, a pytest example, and how it differs from plugins and hooks.
- Vibe coding for Bitrix24: apps and handlers built with an agentHow to hand an agent a Bitrix24 app or handler without getting invented methods: project rules, webhooks, pagination, tests and a session cost.
- MCP in Open WebUI: giving models access to external toolsOpen WebUI can connect MCP servers and hand their tools to models. We cover step-by-step setup, the limits, and what it does to token usage when you work through a gateway.
- MCP in opencode: connecting local and remote serversStep by step MCP setup for opencode: the mcp block in config, headers and OAuth, disabling servers for specific agents, and what extra tools cost.