Back to Job Posting & Applicant Tracking

Developer Handover Pack

Everything needed to build the automation from scratch: current state, full agent specs, data flow, and the build stack.

4 pagesPDF · Technical
FS-DOC-04Technical

Developer Handover Pack

Job Posting & Applicant Tracking

[YourCompany.com] · HR Department · Prepared by FullSpec · [Today's Date]

This document is the authoritative technical reference for the three-agent automation covering job posting and applicant tracking. It is written for the FullSpec build team and covers the current-state process map, per-agent specifications with IO contracts, the end-to-end data flow, and the recommended build stack. Everything the FullSpec team needs to begin implementation without further discovery is contained here. Where a decision is still open, an explicit note flags what must be confirmed before that build stage begins.

01Process snapshot

Step
Name
Description
1
Draft Job Advertisement
HR Coordinator writes a job ad from scratch or edits a saved copy in Google Docs. Owner: HR Coordinator. Time cost: 40 min/hire.
2
Get Hiring Manager Approval
Draft is emailed to the hiring manager for sign-off via Gmail. Responses take one to three days when the manager is busy. Owner: HR Coordinator. Time cost: 15 min to send + 1 to 3 days elapsed.
3
Publish to Job Boards
Coordinator logs into each board (LinkedIn, Indeed, company site) individually and pastes the approved ad. Owner: HR Coordinator. Time cost: 45 min/hire.
4
Create Tracking Spreadsheet Row
A new row is added to the master Google Sheets tracker with role title, hiring manager, target start date, and board links. Owner: HR Coordinator. Time cost: 10 min/hire.
5
Collect and Log Applications
Applications arrive by email and job board portals. Coordinator manually copies name, contact details, and resume link into Google Sheets. Owner: HR Coordinator. Time cost: 60 min/hire.
6
Send Acknowledgement Emails
Each applicant receives a manually composed acknowledgement email in Gmail with light personalisation. Owner: HR Coordinator. Time cost: 25 min/hire.
7
Initial Resume Screen
Coordinator reads each resume and marks candidates as shortlist, hold, or reject in Google Sheets against role criteria. Owner: HR Coordinator. Time cost: 50 min/hire.
8
Notify Hiring Manager of Shortlist
Coordinator emails the hiring manager a list of shortlisted candidates with resume attachments via Gmail. Owner: HR Coordinator. Time cost: 20 min/hire.
9
Schedule Interviews
Coordinator emails shortlisted candidates with available slots and books calendar events on confirmation. Owner: HR Coordinator. Time cost: 30 min/hire.
10
Update Candidate Status in Tracker
After each interview is scheduled or completed the coordinator updates candidate status and notes the interview date in Google Sheets. Owner: HR Coordinator. Time cost: 15 min/hire.
11
Send Rejection Emails
Candidates not progressing receive a manual rejection email individually adapted from a saved template in Gmail. Owner: HR Coordinator. Time cost: 20 min/hire.
12
Collect Interview Feedback
Coordinator follows up with the hiring manager post-interview by email to collect structured or free-text feedback. Owner: HR Coordinator. Time cost: 15 min/hire.
Time cost summary: Total manual time per hire is 345 minutes (5 hours 45 min). At 6 to 10 hires/month this equates to approximately 6.5 manual hours/week across the hiring pipeline. The automation replaces steps 1, 2, 4, 5, 6, 7, 8, and 12 (partially). Steps 3, 9, 10, and 11 remain manual or are assisted. Bottlenecks at steps 2, 5, 7, and 12 account for over half the total elapsed time per hire and are the primary cause of candidate drop-off.
Developer Handover PackPage 1 of 4
FS-DOC-04Technical

02Agent specifications

Job Ad Drafting Agent

Listens for a Greenhouse webhook firing when a vacancy is marked as approved. Pulls the vacancy record fields (role title, department, hiring manager, salary band, and stored job description template) from Greenhouse via the Jobs API, passes them to a prompt template stored in the orchestration layer, and generates a complete, on-brand job advertisement. The draft is dispatched to the hiring manager's Gmail inbox as a structured email containing the ad copy and a single approval link. On approval the agent triggers the job board posting workflow. On rejection it loops back with the hiring manager's revision notes attached.

Trigger
Greenhouse webhook: vacancy status transitions to 'approved'. Event type: job.approved.
Tools
Greenhouse (Jobs API, read), Gmail (send, OAuth 2.0)
Replaces steps
Steps 1 and 2 (Draft Job Advertisement, Get Hiring Manager Approval)
Estimated build
10 hours, Moderate complexity
// Input
greenhouse.job.id          : string   // Greenhouse internal job ID
greenhouse.job.title       : string   // Role title
greenhouse.job.department  : string   // Department name
greenhouse.job.description : string   // Raw JD template stored in Greenhouse
greenhouse.job.hiring_mgr  : string   // Hiring manager email address
greenhouse.job.salary_band : string   // Salary range if public-facing

// Output (on draft sent)
gmail.message.to           : string   // hiring manager email
gmail.message.subject      : string   // '[Action Required] Job Ad Draft: {job.title}'
gmail.message.body         : string   // Generated ad copy + approval/reject links
gmail.message.sent_at      : datetime // ISO 8601 timestamp

// On approval
greenhouse.job.ad_approved : boolean  // Flag set to true on hiring manager click
workflow.next_trigger      : string   // 'post_to_linkedin' event emitted
  • Greenhouse API access must be confirmed before build begins. The Jobs API endpoint requires a Harvest API key with read scope on jobs and job stages. Confirm the key with the Greenhouse admin before week 1 ends.
  • The prompt template must be stored as a named variable in the orchestration layer's credential/config store, not hardcoded. FullSpec will supply an initial version; the HR coordinator must review and approve it against three sample vacancies before the agent goes live.
  • The approval link in the Gmail draft must encode the Greenhouse job ID and a signed HMAC token to prevent spoofed approvals. Token TTL should be set to 72 hours to accommodate busy hiring managers.
  • If the hiring manager does not click within 72 hours, the agent must send one reminder email and then escalate to Slack with a direct mention of the hiring manager's Slack user ID (confirm the ID mapping before build).
  • Revision loop: if the hiring manager clicks 'Request changes', their reply text is captured, appended to the prompt as a correction instruction, and the agent regenerates and re-sends. Maximum two auto-revision loops before flagging for manual intervention.
  • Greenhouse webhook endpoint must be registered under Settings > Dev Center > Web Hooks using the orchestration layer's inbound webhook URL. Confirm the secret key is stored in the credential store, not in plain text.
Application Intake Agent

Monitors Greenhouse for newly submitted application records on any active role. On each new application event it reads the full applicant payload (name, email, phone, resume URL, source channel, and applied-at timestamp), writes a structured record to Greenhouse via the Applications API if not already complete, appends a corresponding row to the live Google Sheets hiring tracker, and dispatches a personalised acknowledgement email via Gmail within five minutes of the application being received. The agent includes a dedupe check against the Greenhouse candidate ID to prevent duplicate records on re-submissions or webhook retries.

Trigger
Greenhouse webhook: new application submitted. Event type: application.created.
Tools
Greenhouse (Applications API, read/write), Google Sheets (Sheets API v4, append), Gmail (send, OAuth 2.0)
Replaces steps
Steps 4, 5, and 6 (Create Tracking Row, Collect and Log Applications, Send Acknowledgement Emails)
Estimated build
10 hours, Moderate complexity
// Input
greenhouse.application.id          : string   // Greenhouse application ID (used for dedupe)
greenhouse.application.candidate_id: string   // Greenhouse candidate ID
greenhouse.application.job_id      : string   // Linked job ID
greenhouse.application.first_name  : string
greenhouse.application.last_name   : string
greenhouse.application.email       : string
greenhouse.application.phone       : string
greenhouse.application.resume_url  : string   // Hosted resume link from Greenhouse
greenhouse.application.source      : string   // e.g. 'LinkedIn', 'Direct'
greenhouse.application.applied_at  : datetime // ISO 8601

// Output (Greenhouse write-back)
greenhouse.application.status      : string   // Set to 'active'
greenhouse.application.tag         : string   // 'intake_complete'

// Output (Google Sheets append)
sheets.row.job_title               : string
sheets.row.candidate_name          : string
sheets.row.email                   : string
sheets.row.phone                   : string
sheets.row.resume_url              : string
sheets.row.source                  : string
sheets.row.applied_at              : datetime
sheets.row.status                  : string   // Default: 'Applied'

// Output (Gmail acknowledgement)
gmail.message.to                   : string   // applicant email
gmail.message.subject              : string   // 'We received your application for {job_title}'
gmail.message.body                 : string   // Personalised template with estimated response timeline
gmail.message.sent_at              : datetime
  • Dedupe logic: before writing to Greenhouse or Sheets, query Greenhouse for any existing application record matching the candidate_id and job_id pair. If a record already exists, skip the write and log a 'duplicate_skipped' entry to the error log table. Do not send a second acknowledgement email.
  • Google Sheets target: confirm the Sheet ID and tab name with the HR coordinator before build. The tab must already exist with header row matching the output field names above. FullSpec will provide the header template.
  • Gmail sending account: must use a verified Gmail address authorised under the [YourCompany.com] Google Workspace. The OAuth 2.0 refresh token must be stored in the orchestration layer's credential store with offline access scope (https://www.googleapis.com/auth/gmail.send).
  • Acknowledgement email template must be reviewed and approved by the HR coordinator before the agent goes live. It should include the role title, a realistic response-time estimate, and a named HR contact for accessibility queries.
  • Greenhouse Applications API rate limit is 50 requests per 10 seconds per key. At 6 to 10 active roles with burst application periods, implement a queue with a 200 ms delay between writes to stay within limits.
  • Source channel field mapping: Greenhouse returns source as a nested object. Extract source.public_name for the Sheets row and for reporting purposes.
Resume Screening Agent

Triggers when an application record in Greenhouse is tagged 'intake_complete' by the Application Intake Agent, confirming the record is fully populated. Reads the resume content from the Greenhouse-hosted URL and evaluates it against the role's defined screening criteria stored as a custom field set on the Greenhouse job record. Assigns a numeric fit score (0 to 100) and a short reasoning note (maximum 80 words). Writes the score, reasoning, and a candidate tag (shortlist, hold, or reject) back to the Greenhouse application record. After all applications for a role batch are scored, compiles a ranked shortlist and sends a Slack notification to the hiring manager's Slack user ID with candidate names, scores, and direct Greenhouse profile links.

Trigger
Greenhouse application tag set to 'intake_complete' by the Application Intake Agent.
Tools
Greenhouse (Applications API, read/write; Jobs API, read for criteria), Slack (Web API, chat.postMessage)
Replaces steps
Steps 7, 8, and 12 (Initial Resume Screen, Notify Hiring Manager of Shortlist, Collect Interview Feedback)
Estimated build
12 hours, Moderate complexity
// Input
greenhouse.application.id             : string   // Application to score
greenhouse.application.resume_url     : string   // Hosted resume document
greenhouse.job.screening_criteria     : string   // Custom field: structured criteria stored on job record
greenhouse.job.id                     : string
greenhouse.job.title                  : string
greenhouse.job.hiring_mgr_slack_id    : string   // Slack user ID for notification

// Output (Greenhouse write-back per application)
greenhouse.application.fit_score      : integer  // 0 to 100
greenhouse.application.score_note     : string   // Max 80 words reasoning
greenhouse.application.tag            : string   // 'shortlist' | 'hold' | 'reject'
greenhouse.application.scored_at      : datetime // ISO 8601

// Output (Slack shortlist notification, sent once per role batch)
slack.message.channel                 : string   // Hiring manager Slack user ID (DM)
slack.message.text                    : string   // Ranked candidate list with scores and links
slack.message.blocks                  : array    // Structured Block Kit payload
slack.message.sent_at                 : datetime
  • Screening criteria must be stored as a structured custom field on the Greenhouse job record before this agent can score reliably. Confirm field name and format (plain text or JSON array) with the Greenhouse admin. FullSpec recommends a JSON array of weighted criteria strings for maximum scoring precision.
  • Resume parsing: fetch the resume from the Greenhouse-hosted URL, extract plain text content, and pass it to the LLM prompt alongside the criteria. PDF and DOCX formats must both be handled. Use a document parsing utility layer in the orchestration platform.
  • Fit score thresholds for tagging: 70 to 100 tags as 'shortlist', 40 to 69 tags as 'hold', 0 to 39 tags as 'reject'. These thresholds must be stored as configurable variables in the credential/config store, not hardcoded, so the HR coordinator can adjust them without a code change.
  • Batch trigger for Slack notification: the agent should not fire a Slack message per application. Implement a batching check: after each score write, query Greenhouse for any remaining 'intake_complete' unscored applications on the same job. Only send the Slack notification when zero unscored applications remain for that job, or after a 4-hour window from the first score in the batch.
  • Slack Block Kit payload must include: candidate full name, fit score as a bold integer, tag as a coloured emoji indicator (green circle for shortlist, yellow for hold, red for reject), and a direct URL to the Greenhouse application profile. Confirm the Greenhouse application profile URL pattern before build.
  • The agent must never auto-reject a candidate without the score and note being written to Greenhouse first. If the LLM call fails, tag the application as 'screening_error' and alert the HR coordinator via Slack rather than defaulting to any tag silently.
Developer Handover PackPage 2 of 4
FS-DOC-04Technical

03End-to-end data flow

Full trigger-to-output data flow: Job Posting & Applicant Tracking automation
// ============================================================
// TRIGGER: Greenhouse vacancy approved
// ============================================================
EVENT: greenhouse.webhook -> job.approved
  payload.job_id          : string   // e.g. 'gh_job_00412'
  payload.job_title       : string   // e.g. 'Senior Marketing Manager'
  payload.department      : string   // e.g. 'Marketing'
  payload.hiring_mgr_email: string   // e.g. 'jordan@yourcompany.com'
  payload.hiring_mgr_slack: string   // e.g. 'U04XKJW29AB'
  payload.salary_band     : string   // e.g. '$70,000 to $85,000'
  payload.jd_template     : string   // Raw JD from Greenhouse custom field

// ============================================================
// AGENT 1: Job Ad Drafting Agent
// ============================================================
AGENT_1_INPUT:
  job_id, job_title, department, hiring_mgr_email, salary_band, jd_template

STEP 1.1: LLM prompt with stored ad template + job fields
  -> ad_draft.body        : string   // Generated ad copy
  -> ad_draft.subject     : string   // Email subject line

STEP 1.2: Gmail send to hiring_mgr_email
  gmail.to                = hiring_mgr_email
  gmail.subject           = '[Action Required] Job Ad Draft: {job_title}'
  gmail.body              = ad_draft.body + approval_link + reject_link
  approval_link.token     = HMAC(job_id + timestamp, secret_key) // TTL 72 hrs

STEP 1.3: Await webhook callback from approval link
  IF approved:
    greenhouse.job.ad_approved = true
    EMIT event: 'post_to_linkedin'
  IF rejected:
    hiring_mgr.revision_notes -> append to prompt -> regenerate (max 2 loops)
  IF timeout (72 hrs):
    SEND Gmail reminder -> IF no response after 24 hrs: ALERT Slack @hiring_mgr

STEP 1.4: LinkedIn post (on approval)
  linkedin.job_post.title     = job_title
  linkedin.job_post.body      = ad_draft.body
  linkedin.job_post.location  = greenhouse.job.location
  linkedin.response.post_url  -> written to greenhouse.job.board_links

// ============================================================
// AGENT 2: Application Intake Agent
// ============================================================
TRIGGER: greenhouse.webhook -> application.created
  payload.application_id  : string
  payload.candidate_id    : string
  payload.job_id          : string
  payload.first_name      : string
  payload.last_name       : string
  payload.email           : string
  payload.phone           : string
  payload.resume_url      : string
  payload.source          : object   // -> extract source.public_name
  payload.applied_at      : datetime

STEP 2.1: Dedupe check
  QUERY greenhouse.applications WHERE candidate_id = payload.candidate_id
    AND job_id = payload.job_id
  IF record exists:
    LOG 'duplicate_skipped' -> error_log table
    HALT

STEP 2.2: Greenhouse write-back (if new)
  greenhouse.application.status = 'active'
  greenhouse.application.tag    = 'intake_complete'

STEP 2.3: Google Sheets append (Sheets API v4)
  sheets.spreadsheet_id   = config.SHEETS_HIRING_TRACKER_ID
  sheets.range            = 'Applications!A:K'
  sheets.row              = [
    job_title, candidate_id, first_name + ' ' + last_name,
    email, phone, resume_url, source.public_name,
    applied_at, 'Applied', '', ''
  ]

STEP 2.4: Gmail acknowledgement send
  gmail.to      = payload.email
  gmail.subject = 'We received your application for {job_title}'
  gmail.body    = template.acknowledgement(first_name, job_title)
  gmail.sent_at -> logged to error_log on failure

// ============================================================
// AGENT 3: Resume Screening Agent
// ============================================================
TRIGGER: greenhouse.application.tag == 'intake_complete'
  application_id, resume_url, job_id, job_title, hiring_mgr_slack_id

STEP 3.1: Fetch screening criteria
  QUERY greenhouse.jobs[job_id].custom_fields.screening_criteria
  -> criteria_array : array  // JSON array of weighted criteria strings

STEP 3.2: Fetch and parse resume
  HTTP GET resume_url -> raw document (PDF | DOCX)
  PARSE -> resume_text : string

STEP 3.3: LLM scoring call
  INPUT: resume_text + criteria_array
  OUTPUT:
    fit_score  : integer  // 0 to 100
    score_note : string   // max 80 words
    tag        : string   // derived from thresholds in config store
      70-100 -> 'shortlist'
      40-69  -> 'hold'
      0-39   -> 'reject'

STEP 3.4: Greenhouse write-back
  greenhouse.application.fit_score = fit_score
  greenhouse.application.score_note = score_note
  greenhouse.application.tag        = tag
  greenhouse.application.scored_at  = NOW()

STEP 3.5: Batch check
  QUERY greenhouse.applications WHERE job_id = job_id
    AND tag NOT IN ['shortlist','hold','reject']
  IF count == 0 OR elapsed_since_first_score >= 4 hrs:
    COMPILE ranked_shortlist (tag='shortlist', sorted by fit_score DESC)
    SEND slack.chat.postMessage to hiring_mgr_slack_id
      blocks: [candidate_name, fit_score, tag_emoji, greenhouse_profile_url]
  ELSE:
    WAIT (next application.scored event)
Developer Handover PackPage 3 of 4
FS-DOC-04Technical

04Recommended build stack

Orchestration layer
One workflow per agent (three workflows total): Job Ad Drafting Agent workflow, Application Intake Agent workflow, Resume Screening Agent workflow. All three workflows share a single credential store within the automation platform. No credentials are stored as inline values in any workflow node. Credential entries are named: GREENHOUSE_HARVEST_API_KEY, GMAIL_OAUTH_REFRESH_TOKEN, GMAIL_OAUTH_CLIENT_ID, GMAIL_OAUTH_CLIENT_SECRET, GOOGLE_SHEETS_SERVICE_ACCOUNT_JSON, SLACK_BOT_TOKEN, LINKEDIN_ACCESS_TOKEN, LLM_API_KEY, APPROVAL_HMAC_SECRET, SHEETS_HIRING_TRACKER_ID, SCORE_THRESHOLD_SHORTLIST (default 70), SCORE_THRESHOLD_HOLD (default 40).
Webhook configuration
Three inbound webhook endpoints are required. (1) Greenhouse job.approved event, registered under Greenhouse Settings > Dev Center > Web Hooks, pointed at the Job Ad Drafting Agent workflow URL. (2) Greenhouse application.created event, pointed at the Application Intake Agent workflow URL. (3) Approval/rejection callback URL for hiring manager email links, handled by a lightweight HTTP trigger node in the Job Ad Drafting Agent workflow that validates the HMAC token before proceeding. All webhook URLs must be HTTPS. Greenhouse requires a secret key per webhook; store it as GREENHOUSE_WEBHOOK_SECRET in the credential store and validate the X-Greenhouse-Token header on every inbound request.
Templating approach
Job ad prompt template stored as a named config variable (AD_PROMPT_TEMPLATE) in the credential store, not in the LLM node directly. Acknowledgement email template stored as a named config variable (ACK_EMAIL_TEMPLATE) with {first_name} and {job_title} as interpolation tokens. Slack Block Kit shortlist template defined as a JSON structure in the Resume Screening Agent workflow with looped candidate blocks. All templates must be reviewed and approved by the HR coordinator before any agent goes live. FullSpec will document how to update each template without a workflow redeploy.
Error logging
A Supabase table named automation_error_log captures every failure event with columns: id (uuid), workflow_name (text), event_type (text), payload_snapshot (jsonb), error_message (text), occurred_at (timestamptz), resolved (boolean, default false). On any unhandled error in any agent, the orchestration layer writes a row to this table and sends a Slack alert to the FullSpec monitoring channel (confirm channel ID before go-live). The HR coordinator receives a daily digest of unresolved rows via Gmail if any exist. Duplicate-skipped events are also logged here for audit purposes but do not trigger an alert.
Testing approach
All three agents are built and tested against the Greenhouse sandbox environment first. Greenhouse provides a demo account with test jobs and applications. Gmail sending is tested against an internal [YourCompany.com] test inbox before live candidate emails are enabled. Google Sheets writes are tested against a duplicate staging tab named 'Applications_TEST' before switching to the production tab. Slack notifications are tested by sending to the FullSpec internal test Slack workspace first. LinkedIn posting is tested using a draft/unpublished post mode where available. A parallel run against one live hire is conducted in week 4 before full go-live.
Estimated total build time
Job Ad Drafting Agent: 10 hours. Application Intake Agent: 10 hours. Resume Screening Agent: 12 hours. End-to-end integration testing and parallel run validation: 6 hours. Total: 38 hours across a 4-week delivery window. The template JSON documents 32 build effort hours for agent development; the additional 6 hours cover cross-agent testing, error log setup, Supabase table provisioning, and handoff documentation.
Three items must be confirmed before the build begins: (1) Greenhouse Harvest API key with read/write scope on jobs and applications, provided by the Greenhouse admin. (2) Screening criteria documented as structured text or JSON for each active role type in Greenhouse, reviewed by the HR coordinator. (3) Slack user IDs for all hiring managers who will receive shortlist notifications, mapped to their Greenhouse hiring manager email addresses. Delays in any of these three items will directly delay the corresponding agent build stage.
For build support or questions during development, contact the FullSpec team at support@gofullspec.com. Include the process name (Job Posting & Applicant Tracking) and the agent name in the subject line.
Developer Handover PackPage 4 of 4

More documents for this process

Every document generated for Job Posting & Applicant Tracking.

Launch Plan
Operations · Owner
View
ROI and Business Case
Finance · Owner
View
Process Runbook / SOP
Operations · Owner
View
Integration and API Spec
Technical · Developer
View
Test and QA Plan
Quality · Developer
View