Section B · Deep dive — primary

Agentic Workflow Architecture for HR

The most-probed technical area: how to design multi-agent systems that span HRIS, ATS, payroll, and ticketing, with the HITL gates and audit posture this domain demands.

Why this is the deep dive

Every loop will have at least one round that boils down to: "Design an end-to-end agentic workflow for [X]." Where X is onboarding, offboarding, a Q&A bot, survey synthesis, or a recruiting pipeline summary. The interviewer is testing whether you can:

  • Decompose the workflow into the right granularity of agents and tools
  • Identify where the human gates go
  • Be explicit about the data flow and where PII crosses system boundaries
  • Reason about failure modes before being asked
  • Make the right n8n vs. Python vs. MCP allocation

This chapter gives you the framework. 06-applied-patterns applies it to specific workflows.

The shape of an HR agentic workflow

The reference architecture, top to bottom:

LayerResponsibilityTypical tool
TriggerWebhook, schedule, manual kickoffn8n trigger nodes, HRIS webhooks, Slack slash command
Context gatherFetch the worker record, the ticket, the policy chunksn8n HTTP nodes, MCP resources, RAG retriever
Agent reasoningPlan, propose actions, draft outputClaude API via n8n's AI node or a Python service
Tool executionRead systems (idempotent), draft side-effects (non-committing)MCP servers, n8n function nodes, Python tool functions
HITL gatePresent proposed actions to a human; capture approval / rejectn8n Slack/email approval nodes, custom HITL UI
CommitExecute the approved action (EIB upload, Slack send, Workday API call)n8n + Python; always with idempotency keys
Audit logPersist every step, prompt, tool call, decision, approverPostgres or warehouse; durable, retained per policy
ObservabilityMetrics, traces, error ratesOpenTelemetry, your APM, structured logs

If you can sketch this on a whiteboard from memory, you've cleared the bar. The rest is variant detail.

Multi-agent design for HR workflows

"Multi-agent" doesn't mean "many models gossiping in a chatroom." It means specialized agents with narrow responsibilities, orchestrated by a top-level supervisor.

Three composition patterns

  • Supervisor + workers — a top-level agent decomposes the request and dispatches to specialized agents. Best for workflows with clear sub-tasks (e.g. onboarding: dispatch to hire_drafter, provisioning_planner, welcome_scheduler).
  • Pipeline — agent A produces output that becomes agent B's input. Best for surveys (clusterer → sentiment scorer → narrative writer).
  • Single agent + many tools — for simple workflows, one agent with a rich tool set beats decomposition. Don't over-engineer.
The default heuristic

Start with single agent + many tools. Decompose only when (1) the system prompt is exceeding ~10K tokens and most of it isn't relevant per call, or (2) different sub-tasks need different models / different temperatures / different evals.

When multi-agent helps

  • Different risk tiers in one flow — onboarding has low-risk (draft welcome email) and high-risk (commit Workday hire). Different agents → different model selection, different HITL policies.
  • Cost optimization — Haiku for triage, Sonnet for drafting, Opus only when needed. Multi-agent makes the cost shape legible.
  • Eval isolation — testing the clusterer separately from the writer is much cleaner than testing the end-to-end blob.

Why n8n is well-suited to HR specifically

This will come up. The reasons are not generic "n8n is nice." They are HR-specific:

  • HRKX operators can read the flow. When you hand off to the People team, they can see what runs when, who approves, what the branches are. Code-first orchestration loses this.
  • Built-in approval nodes. The HITL gate is the most-touched primitive in HR; n8n has Slack/email/webhook approval steps out of the box.
  • Self-hostable. EU employee PII must often stay in EU infrastructure. Self-hosted n8n in your VPC is the simple answer.
  • Native AI nodes. Claude, OpenAI, embedding, vector store — first-class. You don't fight the platform to drop in an agent.
  • Connector breadth. Slack, Gmail, Google Workspace, Notion, Jira, HTTP — the actual day-2 tools HR teams already use.
  • Error workflows. n8n's error workflow pattern lets you route failures to ops without per-node try/except.

What n8n is not good for, and what you'd say in interview:

Honest framing

"I put orchestration, approvals, retries, and connector glue in n8n. I put any heavy AI logic — tool definitions, eval harness, structured-output validation, complex prompt construction — in Python and call it from n8n. That keeps the visual flow readable for HRKX while the AI behavior stays testable and version-controlled."

Tool use across HR systems

The HR systems landscape is fragmented. A typical agent reaches into:

SystemRead patternsWrite patterns
WorkdayRaaS reports, web service (Get_Workers), Prism queriesEIB upload (batch) or web service (transactional) — both HITL-gated
Ashby (ATS)REST API: candidates, applications, jobs, offersStage moves, scheduling — usually low-risk, but offer-letter writes are HITL
Payroll (Workday / ADP / Deel / Remote)Usually read-only from agentsGenerally avoided. Payroll writes go through Payroll Ops
Ticketing (Jira / ServiceNow / Zendesk)Tickets, comments, custom fieldsStatus changes, comments, assignments
Survey (Qualtrics)Response export, free-text fieldsRarely write; sometimes survey-send
Equity (Carta / Shareworks)Grants, vestingAlmost always no
IT provisioning (Okta / Jumpcloud)Group membership, statusOften the agent requests; IT or Okta workflows execute

Two design rules:

  1. Separate read and write tools sharply. Reads are safe, idempotent, cacheable. Writes are HITL-gated and idempotency-keyed.
  2. Writes that touch payroll are not auto-write tools — they are propose-tools. The tool's effect is to add a row to a "proposed actions" table, which then surfaces in a HITL UI.

MCP for sharing HRIS access patterns

MCP (Model Context Protocol) is how you stop re-implementing Workday access in every agent. The pattern:

  • One canonical Workday MCP server — exposes read tools (get_worker, list_supervisory_org, get_business_process_history) and resources (the schema, the field dictionary).
  • One canonical Workday-write MCP server — separate process, separate auth, separate audit. Exposes only "propose" tools that write to a staging table, never directly to Workday.
  • Per-system MCP servers — Ashby, Qualtrics, the policy library, the ticketing system. Each agent picks which servers it connects to.

Benefits in interview-speak:

  • One audit-trail discipline across all agents (every MCP call is logged identically)
  • Access control at the MCP server, not per-agent (huge for compliance)
  • HRKX can extend agents by composing existing MCP servers, no Python required
  • Schema and resources are cached once — every agent inherits the prompt-cache savings
# Workday read MCP server — read-only, safe to expose broadly
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("workday-read")

@mcp.tool()
def get_worker(employee_id: str) -> dict:
    """Fetch a worker record by Workday employee_id."""
    return workday_client.get_worker(employee_id)

@mcp.tool()
def list_supervisory_org(org_id: str) -> list[dict]:
    """List workers in a supervisory org."""
    return workday_client.list_sup_org_members(org_id)

@mcp.resource("workday://schema/worker")
def worker_schema() -> str:
    """The Workday worker object's field dictionary, for prompt context."""
    return WORKER_SCHEMA_DOC

if __name__ == "__main__":
    mcp.run()
# Workday write MCP server — separate process, separate auth, HITL-gated
@mcp.tool()
def propose_job_change(employee_id: str, effective_date: str,
                       new_job_profile: str | None = None,
                       new_supervisor_id: str | None = None,
                       new_fte: float | None = None,
                       reason_code: str = "",
                       rationale: str = "") -> dict:
    """Propose a Workday job change. Does NOT commit. Writes to the
    proposed_actions table and returns the proposal_id for HITL review."""
    proposal = {
        "kind": "job_change",
        "employee_id": employee_id,
        "effective_date": effective_date,
        "fields": {k: v for k, v in {
            "job_profile": new_job_profile,
            "supervisor_id": new_supervisor_id,
            "fte": new_fte,
        }.items() if v is not None},
        "reason_code": reason_code,
        "rationale": rationale,
        "idempotency_key": idem_key("job_change", employee_id, effective_date),
    }
    proposal_id = proposals_db.insert(proposal)
    notify_hitl_channel(proposal_id)
    return {"proposal_id": proposal_id, "status": "awaiting_approval"}
The split that matters

Read-MCP and write-MCP are different processes, with different credentials, in different VPC subnets. An agent that has only the read-MCP attached cannot accidentally propose a Workday change. This is the access-control story you want to be able to draw in interview.

HITL patterns in detail

The HITL gate is a UX problem as much as an engineering one. Four patterns, in increasing strictness:

PatternHow it worksUse for
Sampled reviewAuto-commit; 5-10% sampled for human spot-checkLow-risk reads, non-PII summaries, ticket autoreplies on FAQ
Approve-or-editSlack/email card; human approves or edits + approvesDrafted policy answers, welcome emails, scheduled check-ins
Approve-with-diffHuman sees a structured diff of the proposed change before approvingWorkday writes, EIB uploads, comp changes
Two-key approvalTwo distinct approvers required (e.g. HRBP + Payroll Ops)Severance, equity acceleration, anything cross-functional with money at stake

The approval UI matters. A wall-of-text Slack message is useless. A structured card with "Worker: Jane Doe (W-12345). Current FTE: 1.0. Proposed FTE: 0.8. Effective: 2026-07-01. Reason: voluntary part-time. [Approve] [Reject] [Edit]" — that's the bar.

Worked example: leaver checklist agent

End-to-end, drawn from real interview answers that land well.

Trigger

HRBP marks a termination in Workday → Workday webhook → n8n trigger.

Context gather (read-MCP)

  • get_worker: identity, position, location, country, FTE
  • get_compensation: salary, bonus eligibility, equity
  • get_country_severance_rules: from policy library (MCP resource)
  • get_open_tasks: Jira tickets, pending approvals
  • get_payroll_calendar: current and next two cycles

Agent reasoning (Sonnet, with tools)

System prompt frames: "you are drafting a leaver checklist; you propose actions, you do not commit; if the termination is within 5 business days of payroll cutoff, escalate."

Proposed actions (write-MCP)

  • propose_workday_termination: effective date, reason, last day worked
  • propose_okta_offboarding: groups to remove on last day
  • propose_final_pay_calculation: PTO payout, prorated bonus
  • propose_equity_treatment: per plan rules
  • draft_offboarding_email (non-write tool — returns text)
  • create_jira_ticket: knowledge transfer plan

HITL gate (Slack card)

HRBP approves the offboarding plan. Payroll Ops separately approves the final-pay calculation (two-key).

Commit

Approved proposals execute via n8n. Idempotency keys ensure retry safety. Audit log captures every step.

What an interviewer is listening for

  • You named the payroll-cutoff escalation rule unprompted
  • You separated read and write MCP servers
  • You proposed two-key approval for payroll-affecting steps
  • You called out the audit log and idempotency without being asked

Anti-patterns to call out (and avoid)

Anti-patterns
  • "The agent will write directly to Workday." Never propose this. Writes go through a proposed-actions queue with HITL.
  • "The agent has access to the payroll system." No. Payroll reads are usually fine; payroll writes are off-limits.
  • "Multi-agent because it's cool." If a single agent with 6 tools does the job, that's the right answer.
  • "We log decisions but not prompts." Log everything: input, retrieved context, prompt, tool calls, tool results, output, approver, timestamp. Audit is a regulatory requirement, not a feature.
  • "We retry payroll-touching writes automatically." Never. Idempotency keys help, but the retry policy is "fail closed, page a human."

Framings worth memorizing

  • "I split read-MCP and write-MCP into separate processes with separate credentials. That gives me access control at the protocol boundary, not per-agent."
  • "For payroll-adjacent writes, my tool doesn't commit — it proposes. The orchestrator queues the proposal, the HITL UI presents the diff, the human approves, the commit happens through a separate worker that owns idempotency."
  • "n8n owns orchestration, branching, scheduling, approvals. Python owns heavy AI logic and the MCP servers. They meet at well-defined HTTP boundaries."
  • "My default architecture is single-agent + many tools. I decompose to multi-agent only when sub-tasks need different models or different evals."