Workable MCP server for AI agents

Live

BEARER TOKEN

RECRUITING

Productivity

Workable gives your agent recruiting and HR in one account: move candidates through job pipelines, rate and comment on them, approve offers and requisitions, and manage employees, time off, and time tracking.

  • Per-user credentials: each call uses the actual user's access token, never a shared bot.
  • Encrypted per-tenant vault: AES-256, resolved at request time, never in LLM context.
  • Scoped before every call: pre-call scope check, 90-day SIEM-exportable audit chain.
Workable
agent · Acme Q3
Run
Which candidates for the Account Executive job are in the Interview stage?
S
workable_candidates_list
111ms
Recruiting agent
6 candidates are in the Interview stage for Account Executive. 2 of them applied through referrals.
Sources: Workable candidates, 1 job
workable
6 candidates
18:29
Message Claude...

Tools your recruiting agent reaches for on Workable, scoped per user.

CALL ANY TOOL
66 tools for recruiting and HR in Workable: candidates, jobs, stages, ratings, offers, requisitions, events, employees, time off, and time tracking.
workable_candidate_activities_list
List candidate activities
List the activity stream of a candidate, such as comments, stage moves, ratings and emails. Returns an activities array with each activity's action, body, member, stage and created_at. Use workable_candidate_activities_list for one candidate's history. Use workable_job_activities_list for a whole job.
Parameters
Name
Type
Required
Description
candidate_id
string
Required
ID of the candidate. Get it from the id field of workable_candidates_list or workable_candidate_get. Example: "ce4da98".
actions
string
Optional
Only return these activity actions, comma-separated (for example comment,moved).
limit
integer
Optional
Number of activities to return per page. Workable defaults to 50. Example: 25.
max_id
string
Optional
Return activities with an ID less than or equal to this ID. Example: "2a9b4c".
since_id
string
Optional
Return activities with an ID greater than or equal to this ID. To fetch the next page, copy the since_id value from the paging.next URL of the previous response. Example: "2a9b4c".
updated_after
string
Optional
Only return activities updated at or after this date, ISO 8601. Example: "2024-01-01T00:00:00Z".
workable_candidate_comment_create
Create candidate comment
workable_candidate_copy
Copy candidate
workable_candidate_custom_attribute_update
Update candidate custom attribute
workable_candidate_disqualify
Candidate disqualify
workable_candidate_get
Get candidate
workable_candidate_rating_create
Create candidate rating
workable_candidate_rating_upsert
Upsert candidate rating
workable_candidate_relocate
Candidate relocate
workable_candidate_update
Update candidate
workable_candidates_list
List candidates
workable_departments_list
List departments
workable_employee_documents_add
Add employee documents
workable_employee_fields_list
List employee fields
workable_employee_get
Get employee
workable_event_get
Get event
workable_events_list
List events
workable_job_get
Get job
workable_job_members_list
List job members
workable_job_recruiters_list
List job recruiters
workable_jobs_list
List jobs
workable_offer_reject
Reject offer
workable_recruiters_list
List recruiters
workable_requisition_create
Create requisition
workable_requisition_custom_attributes_list
List requisition custom attributes
workable_requisition_get
Get requisition
workable_requisition_update
Update requisition
workable_stages_list
List stages
workable_time_entry_create
Create time entry
workable_timeoff_categories_list
List timeoff categories

For more tools, view docs.

Build your Agent
Same auth pattern across LangChain, OpenAI, Anthropic, and Google ADK.
Python · LlamaIndex
import { ScalekitClient } from "@scalekit-sdk/node";
import { createReactAgent } from "@langchain/langgraph/prebuilt";

const sk = new ScalekitClient(env.SCALEKIT_ENV_URL, env.SCALEKIT_CLIENT_ID, env.SCALEKIT_CLIENT_SECRET);

// Workable tools scoped to this user
const { tools } = await sk.tools.listScopedTools("user_123", {
  filter: { connectionNames: ["workable"], toolNames: [
    "workable_candidates_list",
    "workable_candidate_move",
    "workable_offer_approve"] },
  pageSize: 100,
});

const agent = createReactAgent({ llm, tools });
await agent.invoke({ messages: [{ role: "user", content: "Move Jordan Lee to the Offer stage for the Account Executive job" }] });
import OpenAI from "openai";
import { ScalekitClient } from "@scalekit-sdk/node";

const sk = new ScalekitClient(env.SCALEKIT_ENV_URL, env.SCALEKIT_CLIENT_ID, env.SCALEKIT_CLIENT_SECRET);
const openai = new OpenAI();

const { tools } = await sk.tools.listScopedTools("user_123", {
  filter: { connectionNames: ["workable"] }, pageSize: 100,
});

const res = await openai.chat.completions.create({
  model: "gpt-5",
  messages: [{ role: "user", content: "Move Jordan Lee to the Offer stage for the Account Executive job" }],
  tools,
});

// Execute the tool call with the user's vaulted Workable access token
await sk.tools.executeTool(res.choices[0].message.tool_calls[0], "user_123");
import Anthropic from "@anthropic-ai/sdk";
import { ScalekitClient } from "@scalekit-sdk/node";

const sk = new ScalekitClient(env.SCALEKIT_ENV_URL, env.SCALEKIT_CLIENT_ID, env.SCALEKIT_CLIENT_SECRET);
const anthropic = new Anthropic();

const { tools } = await sk.tools.listScopedTools("user_123", {
  filter: { connectionNames: ["workable"] }, pageSize: 100,
});

const msg = await anthropic.messages.create({
  model: "claude-sonnet-5",
  max_tokens: 1024,
  messages: [{ role: "user", content: "Move Jordan Lee to the Offer stage for the Account Executive job" }],
  tools,
});

// Tool call runs with the user's vaulted Workable access token
await sk.tools.executeTool(msg.content, "user_123");
import { Agent } from "@google/adk/agents";
import { ScalekitClient } from "@scalekit-sdk/node";

const sk = new ScalekitClient(env.SCALEKIT_ENV_URL, env.SCALEKIT_CLIENT_ID, env.SCALEKIT_CLIENT_SECRET);

const { tools } = await sk.tools.listScopedTools("user_123", {
  filter: { connectionNames: ["workable"] }, pageSize: 100,
});

const agent = new Agent({
  name: "recruiting_agent",
  model: "gemini-2.5-pro",
  instruction: "Workable tools scoped to this user",
  tools,
});

await agent.run("Move Jordan Lee to the Offer stage for the Account Executive job");
Try these prompts
Copy any prompt into your agent. Each maps directly to a Workable tool. Click to copy, paste into your agent, done.
Candidates
Copy the prompt
Copied
List candidates in the Interview stage for the Account Executive job.
Copy the prompt
Copied
Move Jordan Lee to the Offer stage.
Copy the prompt
Copied
Disqualify Sam Lee from the Data Analyst job with a note.
Hiring team
Copy the prompt
Copied
Rate Priya Shah as a strong yes with a comment from today's interview.
Copy the prompt
Copied
Approve the pending offer for Maria Lopez.
Copy the prompt
Copied
Show interviews scheduled for this week.
HR
Copy the prompt
Copied
What are Alex Rivera's time off balances?
Copy the prompt
Copied
Request 2 days of vacation for Dana Kim next Thursday and Friday.
Copy the prompt
Copied
List time off requests from this month.
SEE HOW AUTH WORKS
Each user connects their own Workable access token once, and Scalekit sends it with every call. Access tokens stay vaulted, every call is scope checked, and every action is logged.
1
Authorize
Your user connects
Workable
once. We tie it to their identity and the meetings they approved — no shared bot account, no org-wide access
Who:
user ‘A’
when:
Once per user
access:
Limited to user
2
Store
Their
Workable
token lives in a vault scoped to them. User A's meetings are never reachable by an agent acting for user B, even on the same connection
vault:
encrypted
scope:
per-user
tokens:
auto-refreshed
3
Resolve
When your agent calls a
Workable
tool, we fetch the right token server-side. It never touches your agent, never appears in the LLM context, never shows up in your logs
speed:
~40ms
check:
before every call
seen by:
nobody
4
Audit
Every
Workable
tool call is logged — who triggered it, which meeting was fetched, what came back. 90 days of history, tied to the user who authorized it
history:
90 days
export:
SIEM-ready
logged:
every call
Test other agents
See the same per-user auth pattern across other recruiting and HR connectors.
People Ops and HR teams
Offer letter routing agent
Drafts the offer in PandaDoc, blocks on the hiring manager's approval in Slack, then emails the candidate their e-signature link. Every call runs as the recruiter who triggered it, never a shared HR bot.
People Ops and HR teams
Performance review collector
Collects review feedback from Airtable and Google Forms scoped to each manager's direct reports, writes per-employee summaries to Notion, and DMs the manager a Slack digest.
Test other agents
See the same per-user auth pattern across other recruiting and HR connectors.
PEOPLE OPS
Offer letter routing agent
Draft the offer in PandaDoc, gate it on hiring manager approval in Slack, then email the candidate their signature link.
PEOPLE OPS
Performance review collector agent
Collect review feedback from Airtable and Google Forms per manager, summarise each report in Notion, and DM the digest in Slack.
Why Scalekit
Secure your agent's access. Connectors ship in minutes
01.
Shared tokens break per-user analytics
A shared Workable access token looks fine in a demo. In production every stage move and offer approval looks like one service account, and you cannot tell which user triggered it. Scalekit resolves the credential of the actual user who triggered the agent, never a shared bot.
// shared token
audit → bot_service_account

// scalekit
audit → user_abc ✓
02.
Authentication is not authorization
03.
Multi-tenancy is architectural
04.
Workable today. Ten connectors tomorrow.
“Our agents act across Salesforce, Gong, Google Drive, and more, on behalf of every customer. Scalekit behind the scenes meant we can keep adding tools without ever rebuilding how credentials or tool calling work.”
Venu Madhav Kattagoni
Head of Engineering / Von
FAQs
Frequently Asked Questions
Does the agent access Workable as the user or through a shared token?
As the user. Each user connects their own Workable access token once, and Scalekit sends it with every call. Stage moves, ratings, and approvals the agent records are attributed to that user in your audit trail, not a shared service account.
Where is the Workable access token stored?
In Scalekit's managed AES-256 token vault, namespaced per tenant. To rotate it, the user reconnects with a new access token. Revocation is a single dashboard action. Credentials never appear in prompts, logs, or LLM context.
Can I limit what the agent does in Workable?
Yes. Filter by tool name in listScopedTools to expose only what you want, for example the candidate and job read tools without workable_candidate_disqualify or workable_offer_approve. No Workable tool deletes data. Scalekit also enforces scope checks before every API call.
What happens when a user revokes Workable access?
The connection is invalidated on the next tool call. Subsequent requests for that user fail closed with a clear error. Other users in the tenant remain unaffected. The event is logged for audit.
Do some Workable tools need a user-level access token?
Yes. workable_offer_get, workable_offer_approve, and workable_offer_reject work only with a user-level access token, and so do the performance review template tools. The requisition tools also require the Workable Hiring Plan.
Start in your coding agent
Up and running in one command
Install the Scalekit skill in your editor of choice. Connector, auth, tools, prompt, all wired up
Claude Code REPL
/plugin marketplace add scalekit-inc/claude-code-authstack
/plugin install agentkit@scalekit-auth-stack
Cursor Code REPL
# ~/.cursor/mcp.json
{
""mcpServers"": {
""workable"": {
""url"": ""https://mcp.scalekit.com/workable"",
""headers"": { ""Authorization"": ""Bearer $SCALEKIT_TOKEN"" }
}
}
}
Codex Code REPL
# ~/.codex/config.toml
[mcp_servers.workable]
url = ""https://mcp.scalekit.com/workable""
auth_env = ""SCALEKIT_TOKEN""
Copilot Code REPL
# .vscode/mcp.json
{
""servers"": {
""workable"": {
""url"": ""https://mcp.scalekit.com/workable"",
""type"": ""http""
}
}
}