Vincere is where the desk runs. Your agent searches what you already have before it creates anything, so you do not end up with duplicates, then writes the genuinely new ones in. It reads your jobs, companies and contacts as well.
Vincere is the destination. Sourcing and enrichment feed it.
source against the roles already live in Vincere
fill the contact gaps on records you already hold
interview debriefs onto the candidate record
outreach shaped the way the desk is measured
Ask for the outcome and your agent composes the run itself. Or start from a skill, a whole pipeline it already knows end to end.
browse all skills →Every tool ships with a written playbook, and the agent loads it before the first call. Auth, rate limits, what each call costs, which actions need your approval, and the mistakes worth avoiding. It is the difference between an agent that knows the tool and one that guesses at it.
Read the Vincere docs →HOW in lib/vincere.py.
https://{VINCERE_TENANT}.vincere.io/api/v2.x-api-key (company API key) AND id-token (OAuth id_token, ~30 min TTL).VINCERE_TENANT, VINCERE_API_KEY, VINCERE_ID_TOKEN. Never hardcode.set_id_token(...) or re-set env. github.com/vincere-io/vincere-identity has the flow.Candidates: search_candidates, get_candidate, create_candidate, update_candidate. Reads: search_jobs, get_job, search_companies, search_contacts. Index: reference/docs/vincere/raw/endpoints.md.
job (NOT position) in v2 — confirmed. Search paths carry a trailing slash (/candidate/search/).fl/sort are matrix params on the path (/candidate/search/fl=id,name;sort=created_date asc?q=...), q is a query param. The client passes fl/q as query params; if a search 400s, build the matrix path via request().Production ATS writes — pilot one, confirm, then bulk. Watch for id_token expiry (refresh + retry).
ATS write target: enriched candidates → create_candidate.
lib/vincere.pyImport: from lib.vincere import Vincere → instantiate Vincere() (reads key from env). Generic passthrough: request(method, path, *, params, json).
create_candidate(payload: dict) -> Any — POST /candidate — create a candidate.get_candidate(candidate_id: str, *, fields: str | None = None) -> Anyget_job(job_id: str, *, fields: str | None = None) -> Anysearch_candidates(q: str, *, fl: str | None = None, **params) -> Any — GET /candidate/search/ — q query (Lucene-style), fl=fields (see matrix-param note in module doc).search_companies(q: str, *, fl: str | None = None, **params) -> Any — GET /company/search/.search_contacts(q: str, *, fl: str | None = None, **params) -> Any — GET /contact/search/.search_jobs(q: str, *, fl: str | None = None, **params) -> Any — GET /job/search/ — jobs are job in Vincere v2 (CONFIRMED — not position).set_id_token(id_token: str) — Swap in a freshly-refreshed id_token (they expire ~30 min).update_candidate(candidate_id: str, payload: dict) -> Any