Introduction
This seventh agent design pattern focuses on a critical process in every organization—Employee Onboarding. The Employee Onboarding Agent assists HR departments by automating the document collection, policy acknowledgments, equipment provisioning, and system access setup needed when an employee joins the company. The agent validates the data, makes necessary approvals, and only claims success when it executes actions and produces receipts for each completed task. The agent reduces human error, increases efficiency, and ensures compliance in an otherwise tedious and error-prone process.
The Use Case
A new employee is joining a company, and the onboarding process includes multiple tasks such as collecting personal details, confirming policy acknowledgment, assigning workstations, provisioning access to tools, and assigning mentors. The agent is responsible for collecting personal data, ensuring that required documents are signed, making sure all approvals are in place, and finally provisioning the employee’s access to systems and equipment. Each step is tracked, and no action is finalized until the system can confirm a receipt.
Prompt Contract (agent interface)
# file: contracts/onboarding_v1.yaml
role: "EmployeeOnboardingAgent"
scope: >
Collect personal details, confirm signed documents, assign equipment, and provision system access.
Ask once for missing fields (employee_id, personal_info, policy_acknowledgment, equipment_requested, access_requested).
Propose tool calls; never assert success without a receipt.
output:
type: object
required: [summary, decision, employee_data, next_steps, tool_proposals]
properties:
summary: {type: string, maxWords: 80}
decision: {type: string, enum: ["approve","reject","need_approval","need_more_info"]}
employee_data:
type: object
required: [employee_id, name, department, equipment_assigned, system_access]
properties:
employee_id: {type: string}
name: {type: string}
department: {type: string}
equipment_assigned: {type: array, items: {type: string}, maxItems: 3}
system_access: {type: array, items: {type: string}, maxItems: 5}
citations: {type: array, items: {type: string}}
next_steps: {type: array, items: {type: string}, maxItems: 6}
tool_proposals:
type: array
items:
type: object
required: [name, args, preconditions, idempotency_key]
properties:
name: {type: string, enum: [CollectPersonalData, VerifyPolicyAcknowledgment, AssignEquipment, ProvisionSystemAccess]}
args: {type: object}
preconditions: {type: string}
idempotency_key: {type: string}
policy_id: "onboarding_policy.v3"
citation_rule: "1–2 minimal-span claim_ids per factual sentence"
decoding:
narrative: {top_p: 0.92, temperature: 0.72, stop: ["\n\n## "]}
bullets: {top_p: 0.82, temperature: 0.45}
Example claims (context given to the model)
[
{"claim_id":"policy:equipment:role_based","text":"Laptops must be assigned based on department (e.g., Finance gets MacBook, Sales gets Windows laptop).",
"effective_date":"2025-01-01","source_id":"doc:onboarding_policy_v3","span":"role-based equipment allocation"},
{"claim_id":"policy:access:tools_required","text":"All employees must have access to company email, HR software, and Slack on day one.",
"effective_date":"2025-01-01","source_id":"doc:onboarding_policy_v3","span":"company email, HR software, and Slack"},
{"claim_id":"policy:documentation:mandatory","text":"The new employee must sign the confidentiality agreement and the data protection policy.",
"effective_date":"2025-01-01","source_id":"doc:onboarding_policy_v3","span":"sign confidentiality agreement, data protection policy"}
]
Tool Interfaces (typed, with receipts)
# tools.py
from pydantic import BaseModel
from typing import List, Optional, Dict
from datetime import date
class CollectPersonalDataArgs(BaseModel):
employee_id: str
name: str
department: str
email: str
phone_number: Optional[str] = None
class VerifyPolicyAcknowledgmentArgs(BaseModel):
employee_id: str
policies_acknowledged: List[str]
class AssignEquipmentArgs(BaseModel):
employee_id: str
equipment: List[str] # e.g., ["laptop", "monitor", "keyboard"]
class ProvisionSystemAccessArgs(BaseModel):
employee_id: str
access_list: List[str] # e.g., ["email", "HR system", "Slack"]
class ToolReceipt(BaseModel):
tool: str
ok: bool
ref: str
message: str = ""
data: Optional[Dict] = None
# adapters.py (demo logic)
from tools import *
from datetime import datetime
EQUIPMENT_POLICY = {
"Finance": ["MacBook", "Monitor", "Keyboard"],
"Sales": ["Laptop", "Monitor", "Headset"]
}
ACCESS_POLICY = ["email", "HR system", "Slack"]
def collect_personal_data(a: CollectPersonalDataArgs) -> ToolReceipt:
return ToolReceipt(tool="CollectPersonalData", ok=True, ref=f"data-{a.employee_id}",
message="Personal data collected", data={"employee_id": a.employee_id})
def verify_policy_acknowledgment(a: VerifyPolicyAcknowledgmentArgs) -> ToolReceipt:
required_policies = ["confidentiality agreement", "data protection policy"]
missing_policies = [policy for policy in required_policies if policy not in a.policies_acknowledged]
if missing_policies:
return ToolReceipt(tool="VerifyPolicyAcknowledgment", ok=False, ref="policies-missing",
message=f"Missing required policies: {', '.join(missing_policies)}")
return ToolReceipt(tool="VerifyPolicyAcknowledgment", ok=True, ref="policies-ok", message="Policies acknowledged")
def assign_equipment(a: AssignEquipmentArgs) -> ToolReceipt:
department_equipment = EQUIPMENT_POLICY.get(a.department)
if not department_equipment:
return ToolReceipt(tool="AssignEquipment", ok=False, ref="equip-policy-error", message="No equipment policy found for this department")
return ToolReceipt(tool="AssignEquipment", ok=True, ref=f"equip-{a.employee_id}", data={"equipment": department_equipment})
def provision_system_access(a: ProvisionSystemAccessArgs) -> ToolReceipt:
missing_access = [tool for tool in ACCESS_POLICY if tool not in a.access_list]
if missing_access:
return ToolReceipt(tool="ProvisionSystemAccess", ok=False, ref="access-missing", message=f"Missing access: {', '.join(missing_access)}")
return ToolReceipt(tool="ProvisionSystemAccess", ok=True, ref=f"access-{a.employee_id}", data={"access_granted": ACCESS_POLICY})

Join the conversation! Your thoughts help the community grow.