Публичный код агента для сопровождения карьерного workflow.
- файловый
JsonMemoryStoreдля трёх слоёв памяти и журнала запусков; - registry workflow;
- CLI setup-команда
bootstrapдля private workspace; - workflow
ingest-vacancy, который создаёт каркас вакансии и обновляет runtime-память; - стартовый workflow
analyze-vacancy, который выбирает ролевое резюме и собирает первый fit-анализ; - workflow
intake-adoptions, который переносит vacancy-localadoptions.mdв root review layer (adoptions/inbox/+adoptions/questions/open.md); - workflow
prepare-screening, который по готовой вакансии собирает vacancy-localscreening.mdдля первичного интервью; - workflow
rebuild-master, который синхронизирует managed approved-signals section вresumes/MASTER.mdизadoptions/accepted/MASTER.mdи пишет runtime report вagent_memory/runtime/rebuild-master/latest.md. - workflow
rebuild-role-resume, который синхронизирует managed canonical block в выбранномresumes/<role>.mdиз уже согласованногоresumes/MASTER.mdи optionalknowledge/roles/<role>.md. - workflow
build-linkedin, который собирает per-role LinkedIn draft pack вprofile/linkedin/<target_role>.mdиз canonicalMASTER, выбранного role resume и optional profile metadata, а runtime report пишет вagent_memory/runtime/build-linkedin/<target_role>.md. - workflow
export-resume-pdf, который рендерит проверяемый PDF-артефакт изresumes/MASTER.mdили выбранногоresumes/<role>.md, пишет итоговый файл вprofile/pdf/<target_resume>/<language>-<region>.pdfи сохраняет verification trail вagent_memory/runtime/export-resume-pdf/<target_resume>/<language>-<region>/. - workflow
check-response-monitoring, который проверяет активные строкиresponse-monitoring.xlsx, обновляетАктивнаиОбновлена, выводит журнал проверки в консоль и сохраняет его вagent_memory/runtime/check-response-monitoring/.
Агент ожидает, что private repo содержит каталоги:
vacancies/adoptions/knowledge/profile/agent_memory/agent_memory/config/— локальные runtime-настройки CLI, например defaults для LLM.
python job-application-agent.py --root ../.. bootstrap
python job-application-agent.py --root ../.. list-workflows
python job-application-agent.py --root ../.. ingest-vacancy --company "Example" --position "Engineering Manager" --source-channel "Manual" --source-text "Short vacancy text"
python job-application-agent.py --root ../.. analyze-vacancy --vacancy-id 20260420-example-engineering-manager
python job-application-agent.py --root ../.. intake-adoptions --vacancy-id 20260420-example-engineering-manager
python job-application-agent.py --root ../.. prepare-screening --vacancy-id 20260420-example-engineering-manager
python job-application-agent.py --root ../.. rebuild-master
python job-application-agent.py --root ../.. rebuild-role-resume --target-role CTO
python job-application-agent.py --root ../.. build-linkedin --target-role CTO
python job-application-agent.py --root ../.. export-resume-pdf --target-resume CTO --contact-region EU
python job-application-agent.py --root ../.. check-response-monitoring --dry-run
python job-application-agent.py --root ../.. show-memoryПосле установки пакета в editable-режиме можно запускать без python ...py:
python -m pip install -e .
job-application-agent --root ../.. list-workflowsНа Windows pip может поставить job-application-agent.exe в user Scripts directory, который не добавлен в PATH. В этом случае PowerShell покажет warning вида:
The scripts ... are installed in 'C:\Users\<user>\AppData\Roaming\Python\Python314\Scripts' which is not on PATH.
Проверить команду сразу можно по полному пути:
& "$env:APPDATA\Python\Python314\Scripts\job-application-agent.exe" --root ../.. list-workflowsЧтобы команда работала в новых терминалах без полного пути, добавь Scripts directory в пользовательский PATH:
$scripts = "$env:APPDATA\Python\Python314\Scripts"
[Environment]::SetEnvironmentVariable("Path", [Environment]::GetEnvironmentVariable("Path", "User") + ";$scripts", "User")После этого открой новый PowerShell и проверь:
job-application-agent --root ../.. list-workflowsanalyze-vacancy по умолчанию использует llm_provider=openai и OpenAI Responses API. Для реального запуска обязательны:
OPENAI_API_KEYв окружении или вagent_memory/config/secrets.json;- модель через
--llm-model,APPLICATION_AGENT_LLM_MODELили config-файл.
Несекретные defaults можно держать в workspace-файле agent_memory/config/application-agent.json:
{
"analyze-vacancy": {
"llm_provider": "openai",
"llm_model": "gpt-5.4",
"llm_reasoning_effort": "high",
"llm_reasoning_summary": "auto",
"llm_text_verbosity": "medium",
"target_mode": "balanced",
"include_employer_channels": false
}
}Текущая версия application-agent поддерживает в application-agent.json только секцию analyze-vacancy.
| Ключ | Тип | Значение по умолчанию | Описание |
|---|---|---|---|
llm_provider |
string | openai |
LLM-provider для анализа. Поддерживаются openai и fake; fake нужен для локального smoke-теста без сетевого вызова. |
llm_model |
string | "" |
Модель для реального LLM-запуска. Для llm_provider=openai обязательна: через config, --llm-model или APPLICATION_AGENT_LLM_MODEL. |
llm_temperature |
number/null | null |
Опциональная температура. Для GPT-5.4 mini по умолчанию не задаётся; основной контроль качества идёт через reasoning settings. |
llm_reasoning_effort |
string | "" |
Усилие reasoning для Responses API: обычно low, medium или high. Для текущего агента рекомендуется medium. |
llm_reasoning_summary |
string | "" |
Настройка summary reasoning, если модель и аккаунт её поддерживают. Для отладки удобно auto. |
llm_text_verbosity |
string | "" |
Verbosity текстового ответа Responses API. Для этого workflow рекомендуется medium: достаточно подробно, но без лишней воды. |
target_mode |
string | "" |
Режим позиционирования: conservative, balanced, aggressive. Если не задан, workflow берёт значение из meta.yml или использует balanced при ingest. |
selected_resume |
string | "" |
Ручной override выбора резюме. Обычно лучше не задавать глобально, чтобы workflow сам выбирал роль под вакансию. |
russian_text_skill_path |
string | "" |
Путь к обязательному skill humanize-russian-business-text для русскоязычной генерации. Если не задан, используются APPLICATION_AGENT_RUSSIAN_TEXT_SKILL_PATH, ~/.agents/skills/..., затем ~/.codex/skills/.... |
include_employer_channels |
boolean | false |
Включает employer-facing каналы в анализ там, где workflow это учитывает. Для обычного анализа вакансии рекомендуется false. |
Рекомендованный текущий набор llm_*:
{
"llm_provider": "openai",
"llm_model": "gpt-5.4",
"llm_reasoning_effort": "high",
"llm_reasoning_summary": "auto",
"llm_text_verbosity": "medium",
"russian_text_skill_path": "C:\\Users\\avramko\\.agents\\skills\\humanize-russian-business-text\\SKILL.md"
}Почему так:
analyze-vacancyстроит evidence pack, выбирает ролевое резюме, проверяет требования и просит модель вернуть строгий JSON. Responses API с structured output лучше соответствует этому контракту, чем legacy Chat Completions.gpt-5.4-miniвыбран как стартовый баланс качества, стоимости и скорости для регулярного анализа вакансий.llm_reasoning_effort=mediumдаёт модели достаточно reasoning для сопоставления требований и фактов, но не делает каждый запуск максимально дорогим.llm_text_verbosity=mediumподходит дляanalysis.mdиadoptions.md: результат должен быть содержательным, но не расползаться.- Для русского результата
analyze-vacancyобязательно загружает skillhumanize-russian-business-textи передаёт его текст модели. Без доступного skill workflow должен завершиться ошибкой.
Для финальных запусков сопроводительного письма нужно использовать gpt-5.4 или более сильную модель с llm_reasoning_effort=high и llm_text_verbosity=medium. Режим gpt-5.4-mini с medium reasoning допустим для smoke-проверок и черновиков, но не является рекомендуемым финальным режимом для писем под конкретную вакансию.
Для русскоязычного результата analyze-vacancy выполняет отдельный humanizer-pass для cover_letter_standard и cover_letter_short. Этот проход является обязательным quality gate для OpenAI provider и не должен добавлять новые факты; итоговая подпись добавляется кодом из profile/contact-regions.yml.
Prompt-тексты analyze-vacancy лежат вне Python-кода. Приоритет:
agent_memory/prompts/analyze-vacancy/system.ru.mdagent_memory/prompts/analyze-vacancy/task.ru.mdagent_memory/prompts/analyze-vacancy/cover-letter-contract.ru.md
Если root-файла нет, используется packaged default из src/application_agent/data/prompts/analyze-vacancy/.
Секреты в application-agent.json не записываются. Для локального API key используется agent_memory/config/secrets.json, который должен быть в .gitignore:
{
"OPENAI_API_KEY": "sk-...",
"OPENAI_BASE_URL": "https://api.openai.com/v1"
}Окружение имеет приоритет над secrets.json, поэтому временно переопределить ключ можно так:
$env:OPENAI_API_KEY = "sk-..."
python job-application-agent.py --root ../.. analyze-vacancy --vacancy-id 20260420-example-engineering-managerПриоритет настроек: явные CLI-аргументы выше config-файла, config-файл выше встроенных defaults. Альтернативный путь к config можно передать глобальным параметром до имени команды:
python job-application-agent.py --root ../.. --config ..\..\agent_memory\config\application-agent.json analyze-vacancy --vacancy-id 20260420-example-engineering-managerДля smoke-запуска без сетевого LLM можно использовать fake provider:
python job-application-agent.py --root ../.. analyze-vacancy --vacancy-id 20260420-example-engineering-manager --llm-provider fake --llm-model testpython -m pytest testsЧто делает каждая команда:
python job-application-agent.py --root ../.. bootstrapПроверяет и создаёт базовую структуру рабочего каталога агента в указанном root. Это setup-команда, а не runtime workflow.python job-application-agent.py --root ../.. list-workflowsПоказывает доступные runtime workflow, которые можно запускать через CLI. Setup-командаbootstrapв этот список не входит.python job-application-agent.py --root ../.. ingest-vacancy --company "Example" --position "Engineering Manager" --source-channel "Manual" --source-text "Short vacancy text"Создаёт карточку вакансии, заполняетmeta.yml,source.md,analysis.md,adoptions.md, добавляет строку вresponse-monitoring.xlsxи обновляет runtime memory. Перед запуском в root workspace должен существовать валидныйresponse-monitoring.xlsx; без негоingest-vacancyзавершится ошибкой и не создаст vacancy scaffold. Публикация в git не выполняется автоматически: commit/push остаются отдельным ручным шагом поtooling/git-workflow.md.python job-application-agent.py --root ../.. analyze-vacancy --vacancy-id 20260420-example-engineering-managerВыполняет стартовый анализ уже созданной вакансии: подбирает ролевое резюме и формирует начальный fit-анализ. Для реального LLM-запуска нужныOPENAI_API_KEYи модель. Ключ можно положить вagent_memory/config/secrets.json, а модель — передать через--llm-model,APPLICATION_AGENT_LLM_MODELилиagent_memory/config/application-agent.json.python job-application-agent.py --root ../.. intake-adoptions --vacancy-id 20260420-example-engineering-managerНормализует vacancy-localadoptions.mdв root review layer: рендеритadoptions/inbox/<vacancy_id>.mdи синхронизирует initial unresolved items вadoptions/questions/open.md. Это deterministic intake stage, а не review/acceptance session: сама review-сессия остаётся agent-guided и опирается на helper APIs и runbookagent_memory/workflows/adoptions-review.md.python job-application-agent.py --root ../.. prepare-screening --vacancy-id 20260420-example-engineering-managerПо уже ingest/analyze-подготовленной вакансии создаётvacancies/<vacancy_id>/screening.md, обновляетmeta.ymlдо статусаscreening_preparedи пишет runtime memory без Excel или git side effects. Обязательные входы: существующийvacancy_id, уже собранныеmeta.yml,source.md,analysis.md; опционально можно передать--selected-resume,--output-languageи--preparation-depth.python job-application-agent.py --root ../.. rebuild-masterЧитает current-state approved signals изadoptions/accepted/MASTER.md, детерминированно синхронизирует managed block вresumes/MASTER.mdи обновляет runtime reportagent_memory/runtime/rebuild-master/latest.md. Workflow не переписывает narrative sections целиком: baseline-версия управляет только секциейApproved Permanent Signals, чтобы downstreamrebuild-role-resumeиbuild-linkedinчитали уже согласованныйMASTER.python job-application-agent.py --root ../.. rebuild-role-resume --target-role CTOЧитает managed approved-signals section изresumes/MASTER.md, optional shaping bullets изknowledge/roles/CTO.mdи детерминированно синхронизирует managed block вresumes/CTO.md. Baseline-версия не делает full rewrite всего role resume: она обновляет только parseable managed block и пишет per-role runtime report вagent_memory/runtime/rebuild-role-resume/CTO.md.python job-application-agent.py --root ../.. build-linkedin --target-role CTOЧитает canonicalresumes/MASTER.md, выбранноеresumes/CTO.mdи optionalprofile/contact-regions.yml, затем детерминированно собирает bilingual draft pack вprofile/linkedin/CTO.md. Артефакт содержит executive summary, RU и EN ready-to-paste blocks, filling guide иGAPlist; private contacts не попадают автоматически в public-ready copy, а runtime report пишется вagent_memory/runtime/build-linkedin/CTO.md.python job-application-agent.py --root ../.. export-resume-pdf --target-resume CTO --contact-region EUЧитаетresumes/MASTER.mdили выбранноеresumes/<role>.md, применяет public contact overlay изprofile/contact-regions.ymlтолько к верхнему contact/location surface и рендерит PDF вprofile/pdf/CTO/ru-EU.pdf.--target-resumeобязателен;--output-languageв baseline поддерживает толькоru,--contact-regionпринимаетRU,KZ,EUи по умолчанию берётся изprofile/contact-regions.yml(иначеEU),--template-idсейчас поддерживает толькоdefault. Успешный run обязан сохранитьreport.mdи preview PNG pages вagent_memory/runtime/export-resume-pdf/CTO/ru-EU/; если отсутствуетpdftoppmиз Poppler, workflow завершается явной ошибкой вместо partial success.python job-application-agent.py --root ../.. check-response-monitoring --dry-runПроверяет строкиresponse-monitoring.xlsx, гдеАктивна = Да, сверяет доступность и дату страницы вакансии, выводит журнал в консоль и сохраняет его вagent_memory/runtime/check-response-monitoring/. Без--dry-runкоманда пакетно обновляетD=АктивнаиE=Обновлена;--log-fileзадаёт явный путь к файлу журнала.python job-application-agent.py --root ../.. show-memoryПоказывает текущее содержимое файловой памяти агента: задачи, артефакты и журнал запусков workflow, а также reconciliation-сводку по отсутствующим vacancy artifacts.
analyze-vacancy также умеет стартовать без готового vacancy_id, если передать --company, --position и текст вакансии.
Текущий sequencing для adoptions workflow family:
analyze-vacancyсоздаёт vacancy-local draftvacancies/<id>/adoptions.md.intake-adoptionsпереносит draft в root review storesadoptions/inbox/иadoptions/questions/open.md.- Agent-guided review stage читает context через helper APIs из
application_agent.adoptions_reviewи применяет approved updates вadoptions/accepted/MASTER.md. - Только после этого downstream workflow
rebuild-masterдолжен обновлятьresumes/MASTER.md. - Только после синхронизации
MASTERworkflowrebuild-role-resumeдолжен обновлять конкретноеresumes/<role>.mdиз canonical resume и optionalknowledge/roles/<role>.md, а не из raw vacancy corpus илиadoptions/accepted/напрямую. - Только после этого downstream workflow
build-linkedinдолжен читать обновлённый canonical resume family и собиратьprofile/linkedin/<target_role>.md. - Только после этого downstream workflow
export-resume-pdfдолжен читать уже стабилизированные resume/profile derivatives и собирать durable PDF artifact вprofile/pdf/<target_resume>/вместе с verification trail вagent_memory/runtime/export-resume-pdf/<target_resume>/.
Подробный пошаговый сценарий первого рабочего прогона в private workspace лежит в tooling/run-ingest-analyze.md.
После рефакторинга ingest-vacancy разделён на несколько слоёв с разной ответственностью:
src/application_agent/workflows/ingest_vacancy.pyorchestration-слой workflow: принимает request, запускает enrichment, пишет артефакты вакансии, обновляет runtime memory и инициирует запись в Excel.src/application_agent/workflows/vacancy_sources.pysource/provider-слой: загрузка страницы, парсинг HH и generic career sites, normalisation извлечённых данных, fallback на Playwright для JS-heavy страниц.src/application_agent/workflows/vacancy_rendering.pyrendering-слой: генерацияmeta.yml,source.md,analysis.md,adoptions.md.src/application_agent/integrations/response_monitoring.pyдоменная интеграция сresponse-monitoring.xlsx: проверка mandatory workbook prerequisite, добавление строки ingest и возвратexcel_row.src/application_agent/integrations/playwright_renderer.pyisolated browser fallback для сайтов, где обычный HTML-fetch не даёт полного содержимого вакансии.src/application_agent/normalization/data-driven нормализация справочников и соответствий: страны, source channels, generic page rules.src/application_agent/utils/placeholders.pyединая placeholder-policy для значений вроденет данныхиНе указано.
Ключевые принципы текущей архитектуры:
- workflow должен оперировать доменными сущностями, а не знать детали XLSX, HTML parser internals или справочников;
- справочные данные и соответствия выносятся в data-файлы и отдельные normalisation-модули;
- rendering, parsing и integration logic не должны смешиваться в одном файле;
- browser automation через Playwright включается только как fallback, а не как основной путь ingest.
- более точный fit scoring;
- постоянная память по подтверждённым сигналам;
- orchestration для следующих workflow;
- дополнительная стабилизация generic-page extraction и критериев включения Playwright fallback.
Если агент запускается не из submodule, а из корня private repo, можно передать --root ..