watch_jobs({ query: "iOS jobs in Austin making at least 150k a year with a maximum of 6 years of experience" }) // a week later get_changes()Agent
Job boards,
watched for AI.
Tech job monitoring for AI agents. Say what you are looking for once and get only the new postings that match, from the job boards of tech companies and startups, as structured JSON.
Take the quiz4 quick questions, then a prompt to paste into your agent
Use watchtower.lat (https://watchtower.lat/llms.txt) to watch for iOS roles in Austin, TX paying at least $150k a year with at most 6 years of experience, and tell me about new postings as they appear.
Take the quiz · 4 questions
Four questions. One prompt.
Answer a few questions and get a prompt to paste into your agent. It does the watching from there.
What kind of role?
Pick as many as you like. Every role at tech companies and startups is covered, not only engineering.
Where do you want to work?
Pick as many as you like, or type any city.
Just the city, or the whole area?
The area takes in the towns around it, like Oakland and Palo Alto for San Francisco.
What's the least you'd take?
Yearly, in US dollars. Postings that do not state pay still show up, so you never miss one.
How many years of experience do you have?
Jobs asking for more than this are skipped.
Your prompt is ready.
Tap a colour to change an answer.
Use watchtower.lat to watch for roles in paying at least a year with at most of experience.
Works with any agent that can browse the web or call an API. Or install the MCP server.
Ask once. Hear only what's new.
Watchtower remembers which jobs were open, so your agent doesn't have to.
watch_jobs({ query: "iOS jobs in Austin making at least 150k a year with a maximum of 6 years of experience" })
// later, and every time after
get_changes()→ 2 changes · JOB_ADDED Senior iOS Engineer (Acme), JOB_ADDED iOS Engineer, Payments (Northwind)
Watchtower
One callOnly new, removed or updated jobs, as structured JSON. The watch keeps checking while your agent is off.
- Searching the web for iOS jobs in Austin…
- Opening each company's careers page…
- Reading every posting, including yesterday's…
- Comparing against what it remembers
Re-searching
Every page, every timeStarts from scratch on every check, with pages instead of data, and some boards block it.
watch_jobs({ url: "https://boards.greenhouse.io/acme" })
// later
get_changes()→ 1 change · JOB_REMOVED Data Engineer (New York)
Watchtower
One callOnly new, removed or updated jobs, as structured JSON. The watch keeps checking while your agent is off.
- Opening boards.greenhouse.io/acme…
- Scrolling the full list of openings…
- Reading each posting page…
- Working out what was added or removed
Re-searching
Every page, every timeStarts from scratch on every check, with pages instead of data, and some boards block it.
watch_jobs({
urls: ["https://jobs.lever.co/northwind", "https://jobs.ashbyhq.com/globex"],
seniority: ["senior", "staff"], remote_only: true
})
get_changes()→ [] · nothing new since the last call
Watchtower
One callOnly new, removed or updated jobs, as structured JSON. The watch keeps checking while your agent is off.
- Opening two job boards…
- Filtering by title and location by hand…
- Reading every remote posting again…
- Reporting the same jobs as last time
Re-searching
Every page, every timeStarts from scratch on every check, with pages instead of data, and some boards block it.
Every board.
One watch.
Six MCP tools, the same operations over REST. Watch Greenhouse, Lever, Ashby, Workable, SmartRecruiters, Recruitee, Workday, iCIMS, Oracle Recruiting, Eightfold, SuccessFactors, Apple, Google, Amazon, Microsoft boards, or any careers page with schema.org JobPosting, and filters live on the watch, so get_changes only returns what matters.
- query
- url / urls
- filters
- webhook_url
- interval_minutes
- label
boards.greenhouse.io/acme
- since
- limit
- peek
- watch_id
jobs.lever.co/acme
- keywords
- all_keywords
- exclude_keywords
- locations
- seniority
- remote_only
- min_salary
- max_experience_years
jobs.ashbyhq.com/acme
apply.workable.com/acme
- JOB_ADDED
- JOB_REMOVED
- JOB_UPDATED
jobs.smartrecruiters.com/Acme
Acknowledge a cursor after get_changes(peek=true), for at-least-once processing.
acme.recruitee.com
acme.wd5.myworkdayjobs.com/Careers. Boards over 200 postings report the newest 200.
- health and pending counts
- jobs open now that match
- free a watch slot
careers-acme.icims.com
Read from schema.org JobPosting markup. Pages without it are rejected up front with NO_JOB_DATA.
- poll get_changes
- signed webhook_url
- ETag / Last-Modified honored
Install for free
Connect to Claude Code
- Run this in a terminal
- Ask Claude to watch jobs for you
claude mcp add --transport http watchtower https://watchtower.lat/mcp?ref=claude-code
Connect to Claude
- Open Settings → Connectors
- Choose Add custom connector and paste this URL
- No account needed: Watchtower uses an anonymous client
https://watchtower.lat/mcp
Connect to Cursor
- Click the button: Cursor opens with the server filled in
- Confirm, then ask the agent to watch jobs
https://watchtower.lat/mcp
Connect to VS Code
- Click the button: VS Code opens with the server filled in
- Confirm, then ask Copilot to watch jobs
https://watchtower.lat/mcp
Connect any MCP client
- Add this to the client's MCP config (Streamable HTTP)
- Clients with OAuth connect in one click (add
?auth=requiredto the URL if yours only signs in when asked). Otherwise sendAuthorization: Bearer <token>with a token fromPOST /v1/clients
{
"mcpServers": {
"watchtower": {
"type": "http",
"url": "https://watchtower.lat/mcp"
}
}
}Three calls over HTTP
TOKEN=$(curl -s -X POST https://watchtower.lat/v1/clients | jq -r .token) # every new matching job, on any monitored board curl -s -X POST https://watchtower.lat/v1/watches \ -H "Authorization: Bearer $TOKEN" -H "content-type: application/json" \ -d '{"query":"iOS jobs in Austin making at least 150k a year with a maximum of 6 years of experience"}' # or specific companies' boards curl -s -X POST https://watchtower.lat/v1/watches \ -H "Authorization: Bearer $TOKEN" -H "content-type: application/json" \ -d '{"urls":["https://boards.greenhouse.io/acme","https://jobs.lever.co/acme"],"keywords":["iOS"],"seniority":["senior","staff"],"remote_only":true}' curl -s https://watchtower.lat/v1/changes -H "Authorization: Bearer $TOKEN"
https://watchtower.lat/v1
What a change looks like
{
"id": 1842,
"type": "JOB_ADDED",
"summary": "New job: Senior iOS Engineer (Austin, TX)",
"data": { "job": { "title": "Senior iOS Engineer", "company": "Acme", "location": "Austin, TX", "remote": false, "seniority": "senior",
"salary": { "min": 165000, "max": 210000, "currency": "USD", "period": "year", "annual_min": 165000, "annual_max": 210000 },
"experience_years": 5, "url": "https://..." } }
}Types: JOB_ADDED, JOB_REMOVED, JOB_UPDATED. JOB_UPDATED adds before and changed_fields.
Polite by design.
Free and anonymous, with limits that keep it that way for everyone.
How Watchtower fetches
Public job boards only, read the way each one publishes its jobs.
One per board. Checks at most every 5 minutes. Watches nobody reads for 30 days expire.
At most one request at a time per website, spaced out, with ETag / Last-Modified honored.
Many agents watching the same board cost one request.
No CAPTCHA, login, paywall or anti-bot bypassing. Private and internal network addresses are refused.
Fair questions.
More in the docs, or open an issue.
Is this a crawler or a scraper?
Neither in the usual sense. Supported platforms are read through their own public job-board endpoints, and other careers pages through the schema.org JobPosting markup they publish. Watchtower respects robots.txt and never bypasses CAPTCHAs, logins, paywalls or anti-bot systems.
Which agents does it work in?
Any MCP client (Claude Code, Claude.ai, Claude Desktop, Cursor, VS Code and the rest) over Streamable HTTP, or anything that can make HTTP requests through the REST API.
What does it cost?
Nothing. Watchtower is free and anonymous: no sign-up, no email, no API key to request. Connecting creates an anonymous client in one click.
Which companies are covered?
A built-in directory of tech company and startup boards, from large public companies to seed-stage startups, plus every board anyone watches by URL. Every role they post is covered, not only engineering. See the full list of companies. To add a missing company, watch its board URL (or its careers page); it then stays covered for everyone.
What if a posting does not state pay or experience?
Pay and experience come from what each posting states. Postings that state neither are still reported, without those fields, unless you pass include_unknown: false.
What if my query is read wrong?
The response shows how it was read (interpreted) and the matching jobs open right now. Pass explicit filters to correct it; they override the query.
Can it run on a schedule, unattended?
Yes: that is the point. Watches are checked on a schedule whether or not your agent is running. Add a webhook_url for a signed POST on every matching change, or use get_changes(peek=true) then ack_changes(cursor) for at-least-once processing.
What do you store?
Your watches, a hash of your token and request counts for rate limiting. No accounts, no ads, nothing sold. The privacy page has the details and retention periods.