The Agent Contract
AGENTS.md — intent routing, the gate contract, artifact rules, and write-back invariants.
AGENTS.md in the repo root is the agent's operating contract. Claude Code and
Codex are the two supported product choices, and each uses a CareerRat-owned
direct adapter to run the same contract. The selected installed CLI is invoked
directly; CareerRat never silently switches to another provider. ACP adapters
remain diagnostic-only until they pass the full product boundary and packaged
acceptance matrix. See Why Only Two Supported Engines? for
what that boundary actually checks. The file is the source of truth; this page summarizes the key
sections. CareerRat, not a provider's session history, owns the durable workflow
and thread state.
Paul's user-facing voice is part of that shared contract. It uses ordinary language instead of internal product or recruiting jargon. When a question asks the candidate to make an abstract choice, Paul includes two or three concrete examples so the answer is obvious without extra explanation.
Intent routing
The agent routes any user input — a job paste, a recruiter email, a question, a command — to the owning skill without you naming a skill explicitly. The routing table is extensive; a few key examples:
| What you say or paste | Routed to |
|---|---|
| A job description or URL | evaluate-job (then apply-job if apply intent) |
| "Apply to this" | apply-job |
| "Find jobs" / "run a search" | search-jobs |
| A recruiter / hiring email | email-comms |
| An interview invite | interview-prep |
| A rejection / offer / status change | track-outcomes |
| "Schedule this" / availability thread | schedule-meeting |
| "Research this company" | research-company |
| "Optimize my LinkedIn" | optimize-linkedin |
| Resume / profile facts | ingest-profile |
| "Change a setting" | configure |
Paste routing is universal: anything dropped into the agent chat gets classified, captured, and routed — nothing evaporates.
Gate contract
evaluate-job is the shared mandatory gate. No tailoring, filling, or submission
can proceed without a KEEP verdict (or an explicit user-approved REVIEW).
apply-job runs or verifies evaluate-job as step zero. It cannot skip this
step, even when the user says "just apply." Supervised automation may fill safe,
confirmed fields and attach documents. Voluntary demographic and self-identification
questions stay blank by default. The local-only Profile > Application defaults editor
can keep them blank or choose the form's decline option when available. An existing exact
answer is eligible only when the candidate explicitly saved it. CareerRat never infers one,
and this setting never enters Paul's context. CareerRat may use ordinary Next or Continue controls
while filling a multi-step form, but it never activates a control that submits the application or
confirms a submission. The user handles CAPTCHAs, reviews the prepared form, and performs the final
submit.
Data Write Contract
In a database-backed workspace, every tracker-visible mutation goes through a
documented careerrat data <verb>. One transaction updates the canonical row,
freshness/version metadata, the Activity Pulse, relevant analytics, and the
compatibility exports. The skill then verifies the result with:
careerrat data verifycareerrat tracker --verify
Legacy JSON-only workspaces follow the separate Tracker Write Contract in
AGENTS.md. Database-backed exports must never be hand-edited.
Artifact rules
- Every generated artifact (résumé, cover letter, email) must be complete — no
templates, no
[Placeholder]tokens. - Artifacts land in two places: the tracker record (for dashboard access) and
~/Downloads/careerrat/<Company>/(convenience copy). - Placeholder lint runs before any artifact is marked build-ready. An unresolved bracket blocks the build.
- The agent never invents facts. Claims trace to
.careerrat/candidate/evidence.yml.
The body-read gate invariant
The JD body is captured locally at grab time — when a posting is sourced, evaluated, or applied to. A link is never a substitute: postings vanish when a req closes or goes behind a login. The gate reads the locally saved body, not a live URL, so evaluation stays possible even after the req is taken down.
Privacy invariant
profile.yml#compensation.current_base is private. It informs comp strategy but
must never appear in any outbound artifact (résumé, cover letter, recruiter
message, interview packet, tracker note that could be shared). Outbound comp
anchors on target_base. Skills that produce outbound text route around
current_base by field path.
Domain-neutral rule
Skills and code never hardcode personal, role, tech, comp, region, board, or
company preferences. Every such bias lives in .careerrat/candidate/ config files. A
trucking candidate and an AI engineer run the same skills with different configs
and get different behavior.
Round vocabulary
Interview rounds are named by type, never numbered:
conversations[].kind | Rung shown |
|---|---|
recruiter screen | Screen |
assessment | Assessment |
technical | Technical |
hiring manager | Hiring manager |
onsite | Onsite |
final | Final |
offer | Offer |
The dashboard derives an application's pipeline rung from the deepest kind it
can classify. "Round 2" is never written.