Back to Device & Hardware Management

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

Device and Hardware Management

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

This document is the primary technical reference for the FullSpec build team delivering the Device and Hardware Management automation. It covers the full current-state step map, all three agent specifications with IO contracts, the end-to-end data flow, and the recommended build stack. The FullSpec team owns every build, integration, and testing task described here. Your IT team's only ongoing responsibility is physical device handover, condition checks on return, and responding to exception escalations surfaced by the automation.

01Process snapshot

Step
Name
Description
1
Receive Device Request or Hire Notification
IT receives a Slack message, email, or HR system notification that a new hire is starting or an existing employee needs a device. Notification is usually informal with inconsistent detail. Time cost: 10 min.
2
Check Asset Register for Available Devices
The coordinator opens the shared spreadsheet or Airtable base and manually searches for an unassigned device matching the required spec. Often surfaces stale or incorrect availability records. Time cost: 15 min.
3
Raise Procurement Request if No Device Available
If no suitable device is in stock, the coordinator emails the finance or procurement contact with the spec and estimated cost. Approval can take days and is tracked informally. Time cost: 20 min.
4
Prepare and Configure Device
The coordinator locates the physical device, runs MDM enrollment or confirms existing enrollment in Jamf, and installs required software profiles. Configuration time varies by device age and spec. Time cost: 45 min.
5
Update Asset Register with Assignment
The coordinator manually edits the spreadsheet to record the device serial number, assigned user, assignment date, and expected return date. This step is frequently skipped when the coordinator is busy. Time cost: 10 min.
6
Send Assignment Confirmation to Employee
An email is manually drafted to the employee confirming the device details, acceptable-use policy links, and return expectations. No standard template exists so wording varies. Time cost: 10 min.
7
Log Ticket in Jira
The coordinator opens Jira and creates or updates an IT service ticket to document the assignment event and maintain an audit trail beyond the spreadsheet. Time cost: 8 min.
8
Schedule Periodic Audit Reminder
The coordinator manually sets a calendar reminder or sends a Slack message to prompt a quarterly audit. No automated follow-up exists if the audit does not happen on time. Time cost: 5 min.
9
Conduct Manual Device Audit
Quarterly, the coordinator emails or messages all staff to confirm serial numbers and condition of their devices. Responses trickle in over days and must be reconciled manually against the register. Time cost: 90 min.
10
Process Device Return on Offboarding
When a leaver is confirmed, the coordinator contacts them or their manager to arrange device return, checks the device back in physically, and updates the register. Often missed until the last day. Time cost: 20 min.
11
Wipe and Re-enroll Returned Device
The returned device is wiped via Jamf and re-enrolled as available stock. The coordinator must manually update the register again to mark it unassigned and note its condition. Time cost: 30 min.
12
Flag End-of-Life Devices for Disposal
The IT Manager periodically reviews the register for devices past their useful life and emails the finance team to arrange disposal or trade-in. No automated trigger exists for this step. Time cost: 15 min.
Time cost summary: Total manual time per full device lifecycle cycle is 278 minutes (approx. 4 hours 38 min). At roughly 40 device events per month the team carries approximately 6 hours of manual work every week. Steps 2, 3, 5, 6, 7, 8, 9, 10, 11, and 12 are replaced by automation. Steps 1 (notification receipt) and 4 (physical device configuration and handover) remain with the IT Coordinator. Step 4 is partially assisted by MDM Sync but cannot be fully automated because eyes-on condition verification is required.
Developer Handover PackPage 1 of 4
FS-DOC-04Technical

02Agent specifications

Asset Register Agent

Monitors incoming device events from Jira and HR triggers, queries the Airtable register for availability, and writes assignment or return records back automatically. It handles all lookup and record-keeping work that currently falls to the IT Coordinator, including availability checking, register writes on assignment, register updates on return, and Jira ticket creation or update. This is the central orchestration agent: the other two agents fire in response to record writes it produces. Complexity: Moderate. Estimated build time: 14 hours.

Trigger
Jira ticket created or updated (event types: new_hire_device, offboarding_return, device_request); or HR webhook POST containing hire or departure payload; or daily Google Sheets sync if HR webhook is unavailable.
Tools
Airtable (asset register read and write), Jira (ticket read, create, update)
Replaces steps
2, 5, 7, 10, 12
Estimated build
14 hours — Moderate
// Input
jira_event.issue_type       // 'new_hire_device' | 'offboarding_return' | 'device_request'
jira_event.assignee_email   // target employee email
jira_event.required_spec    // e.g. 'MacBook Pro 14 M3'
jira_event.expected_return  // ISO 8601 date, nullable
hr_webhook.employee_id      // fallback join key if Jira field is absent

// Output (on device found)
airtable_record.device_id          // Airtable record ID
airtable_record.serial_number      // device serial
airtable_record.status             // 'assigned' | 'available' | 'pending_wipe'
airtable_record.assigned_to_email  // employee email written to record
airtable_record.assignment_date    // UTC timestamp
airtable_record.expected_return    // ISO 8601 date
jira_ticket.id                     // created or updated ticket ID
jira_ticket.status                 // 'In Progress' | 'Awaiting Handover'

// Output (no device found)
availability_flag: false
procurement_alert_payload          // passed to Device Lifecycle Comms Agent
  • Airtable base must be on the Team plan or above to support API write access; confirm the base ID and the 'Devices' table schema before build begins. Required fields: device_id (auto), serial_number (text), status (single select: available, assigned, pending_wipe, retired), assigned_to_email (email), assignment_date (date), expected_return (date), spec (text), condition (single select: good, fair, poor).
  • Jira project key must be confirmed. The agent uses the Jira REST API v3. Issue type names must match exactly: 'new_hire_device', 'offboarding_return', 'device_request'. Custom issue types need remapping before build.
  • Deduplication: before writing a new assignment record, the agent queries Airtable for any existing record with the same serial_number and status 'assigned'. If found, it logs a conflict and halts rather than creating a duplicate.
  • Fallback for HR events: if no Jira ticket exists for a hire or departure, the agent accepts a daily Google Sheets export row as a trigger source. The sheet must contain columns: employee_email, event_type, event_date, required_spec.
  • The step-12 end-of-life flag is implemented as a nightly scheduled query: any device with assignment_date older than 36 months or condition set to 'poor' is written to an 'eol_flagged' view in Airtable and a summary is posted to the IT Slack channel. No automatic disposal action is taken.
  • Confirm with IT Manager that Airtable API token has read and write scope on the Devices table and read scope on the Staff table before build kickoff.
Device Lifecycle Comms Agent

Handles all outbound communication triggered by device events: assignment confirmations, audit request emails, overdue return reminders, and procurement alerts. It fires on record changes written by the Asset Register Agent or on a scheduled trigger for the quarterly audit cycle. Every message uses a stored template with dynamic fields pulled from Airtable so wording is consistent across all events. This agent replaces all manual email drafting and the manual Slack reminder step. Complexity: Simple. Estimated build time: 8 hours.

Trigger
Airtable record write by Asset Register Agent (status changes to 'assigned' or 'pending_wipe'); scheduled cron for quarterly audit (every 90 days); overdue return check runs daily at 08:00 UTC and compares expected_return against current date.
Tools
Gmail (outbound email via OAuth service account), Slack (IT channel webhook and manager DM webhook)
Replaces steps
3, 6, 8, 9
Estimated build
8 hours — Simple
// Input (assignment confirmation)
airtable_record.assigned_to_email
airtable_record.serial_number
airtable_record.assignment_date
airtable_record.expected_return
template_id: 'device_assignment_confirmation'

// Input (audit cycle)
airtable_view: 'all_active_assignments'  // list of current assigned records
audit_period: 'Q2 2025'                  // injected from scheduled trigger

// Input (overdue return)
airtable_record.assigned_to_email
airtable_record.serial_number
airtable_record.expected_return
days_overdue: integer

// Output
gmail.message_id         // sent message ID logged to Airtable comms_log field
slack.message_ts         // Slack message timestamp
airtable_record.last_comms_sent  // UTC timestamp written back to record
  • Gmail OAuth must be authorised against the IT team's shared Gmail account (not a personal account). Scope required: gmail.send. The service account must be set up under Google Workspace with domain-wide delegation if sending on behalf of a distribution address.
  • Three email templates must be created and version-controlled before build: 'device_assignment_confirmation', 'quarterly_audit_request', and 'overdue_return_reminder'. Each template uses Airtable field tokens ({serial_number}, {assigned_to_name}, {expected_return}, {days_overdue}).
  • Slack alerts use two separate webhooks: one posting to the #it-ops channel for general events, and one posting a DM to the IT Manager for procurement alerts and overdue returns exceeding 14 days. Both webhook URLs must be supplied before build.
  • The quarterly audit email instructs recipients to reply with a confirmation or to complete a linked Airtable form. The form approach is preferred because it avoids inconsistent free-text replies. Confirm with the IT Manager which method to use; form requires an Airtable form URL to be embedded in the template.
  • Deduplication: the agent checks airtable_record.last_comms_sent before sending a reminder. If a reminder was sent within the past 48 hours for the same record, it skips and logs a suppression note.
MDM Sync Agent

Calls the Jamf Pro API when a device is assigned or returned to verify enrollment status, apply the correct policy profile, and trigger a remote wipe on returned devices before they are marked available again. It fires on Airtable record writes from the Asset Register Agent and writes its results back to the same record. Any enrollment error is flagged to the IT Coordinator via the Device Lifecycle Comms Agent rather than silently failing. Physical wipe confirmation still requires a human to verify the device is received and in acceptable condition before the record status advances to 'available'. Complexity: Moderate. Estimated build time: 12 hours.

Trigger
Airtable record write by Asset Register Agent where status transitions to 'assigned' (triggers enrollment check) or 'pending_wipe' (triggers remote wipe command).
Tools
Jamf Pro API (device lookup, policy apply, remote wipe command), Airtable (enrollment status write-back)
Replaces steps
4 (partially), 11
Estimated build
12 hours — Moderate
// Input (assignment)
airtable_record.serial_number   // used as Jamf device lookup key
airtable_record.assigned_to_email
jamf_policy_profile_id          // supplied per device category in config

// Input (return / wipe)
airtable_record.serial_number
airtable_record.device_id
wipe_command: 'EraseDevice'     // Jamf MDM command

// Output (assignment)
jamf_device.managed_id          // Jamf device record ID
jamf_device.enrollment_status   // 'enrolled' | 'not_enrolled' | 'error'
jamf_device.policy_applied      // boolean
airtable_record.jamf_managed_id // written back
airtable_record.enrollment_status // written back

// Output (wipe)
jamf_wipe.command_status        // 'Pending' | 'Completed' | 'Failed'
airtable_record.wipe_status     // written back
airtable_record.status          // remains 'pending_wipe' until human confirms receipt

// On enrollment error
error_payload.serial_number
error_payload.error_code        // Jamf API HTTP status + message
error_payload.flagged_for_review // true — triggers Comms Agent IT alert
  • Jamf Pro API requires an API role with the following minimum permissions: 'Read Computers', 'Send Computer Remote Wipe Command', 'Update Computer Management Data', 'Read Mobile Devices' (if tablets are in scope). A dedicated API service account must be created in Jamf; do not use a named user account.
  • Self-hosted Jamf Pro instances may sit behind a firewall or VPN. Confirm with the IT Manager that the automation platform's outbound IP range can reach the Jamf host URL on port 443 before build begins. Cloud-hosted Jamf Pro (Jamf Cloud) has no additional network requirement.
  • The agent uses the Jamf Pro REST API (v1) for all calls. The Classic API is not used. Base URL pattern: https://{instance}.jamfcloud.com/api/v1/. Bearer token authentication is used with a token refresh cycle of 30 minutes.
  • Policy profile IDs for each device category (MacBook, iPad, PC) must be documented and supplied in the agent configuration before build. A minimum of three profiles is assumed: 'standard_employee', 'contractor', 'shared_device'.
  • The remote wipe command sets airtable_record.status to 'pending_wipe', not 'available'. The status advances to 'available' only after the IT Coordinator manually marks the device as physically received and inspected. This field update triggers the Comms Agent to post a re-stock alert to the IT Slack channel.
  • If the Jamf API returns a non-200 response, the agent retries twice with a 60-second backoff before writing an error flag to Airtable and triggering a Comms Agent alert to the IT Coordinator. Errors are also written to the error log table in Supabase.
Developer Handover PackPage 2 of 4
FS-DOC-04Technical

03End-to-end data flow

Full trigger-to-output data flow for all three agents, including field names, API endpoints, and agent handoff points.
// ============================================================
// DEVICE AND HARDWARE MANAGEMENT — END-TO-END DATA FLOW
// ============================================================

// TRIGGER
// Source: Jira webhook (issue created/updated) OR HR webhook POST OR Google Sheets daily sync
inbound_event = {
  source:          'jira' | 'hr_webhook' | 'sheets_sync',
  event_type:      'new_hire_device' | 'offboarding_return' | 'device_request',
  assignee_email:  string,           // e.g. 'jane.doe@yourcompany.com'
  required_spec:   string,           // e.g. 'MacBook Pro 14 M3'
  expected_return: string | null,    // ISO 8601 date
  employee_id:     string            // HR system ID, used as fallback join key
}

// ============================================================
// AGENT 1 — Asset Register Agent
// ============================================================

// Step 1: Query Airtable for matching available device
airtable_query = {
  table:   'Devices',
  filter:  "status = 'available' AND spec = inbound_event.required_spec",
  fields:  ['device_id','serial_number','spec','condition','jamf_managed_id']
}
airtable_result = Airtable.GET /v0/{base_id}/Devices?filterByFormula=...

// Step 2: Availability decision
IF airtable_result.records.length === 0:
  // No device available — build procurement alert payload
  procurement_payload = {
    required_spec:   inbound_event.required_spec,
    requestor_email: inbound_event.assignee_email,
    event_type:      inbound_event.event_type
  }
  // Hand off to Device Lifecycle Comms Agent (procurement path)
  --> AGENT 2 (procurement_alert, slack_it_manager)
  HALT

ELSE:
  selected_device = airtable_result.records[0]   // first matching record
  // selected_device.serial_number  e.g. 'C02XJ1YZJGH5'
  // selected_device.device_id      e.g. 'recABC123XYZ'

// Step 3: Write assignment record to Airtable
airtable_write = Airtable.PATCH /v0/{base_id}/Devices/{selected_device.device_id}
  body: {
    status:             'assigned',
    assigned_to_email:  inbound_event.assignee_email,
    assignment_date:    utc_now(),
    expected_return:    inbound_event.expected_return
  }
// Returns: updated_record with all fields

// Step 4: Create or update Jira ticket
IF inbound_event.source === 'jira':
  jira_update = Jira.PUT /rest/api/3/issue/{jira_event.issue_id}
    body: { fields: { status: 'In Progress', serial_number_cf: selected_device.serial_number } }
ELSE:
  jira_create = Jira.POST /rest/api/3/issue
    body: {
      project:    { key: 'IT' },
      issuetype:  { name: inbound_event.event_type },
      summary:    'Device assignment: ' + inbound_event.assignee_email,
      serial_number_cf: selected_device.serial_number
    }
// Output: jira_ticket.id, jira_ticket.key (e.g. 'IT-4821')

// ============================================================
// AGENT HANDOFF 1 → 3 — Asset Register Agent to MDM Sync Agent
// Trigger: Airtable record status set to 'assigned'
// ============================================================

// ============================================================
// AGENT 3 — MDM Sync Agent (fires in parallel with Comms Agent)
// ============================================================

// Step 5: Jamf enrollment check
jamf_token = Jamf.POST /api/v1/auth/token
  headers: { Authorization: Basic {base64(api_user:api_pass)} }
// Returns: token (valid 30 min)

jamf_lookup = Jamf.GET /api/v1/computers-inventory?filter=serialNumber=={serial_number}
// Returns: { id, serialNumber, managementId, enrollmentStatus }

IF jamf_lookup.enrollmentStatus !== 'ENROLLED':
  error_payload = { serial_number, error_code: 'NOT_ENROLLED', flagged_for_review: true }
  --> AGENT 2 (enrollment_error_alert, gmail_it_coordinator)
  Supabase.INSERT INTO error_log (serial_number, error_code, ts)
  HALT

// Step 6: Apply policy profile
jamf_policy = Jamf.POST /api/v1/preview/mdm/commands
  body: {
    commandType: 'SETTINGS',
    managementIds: [jamf_lookup.managementId],
    profileId: config.policy_profile_id[device_category]
  }
// Returns: command_uuid

// Write Jamf result back to Airtable
Airtable.PATCH /v0/{base_id}/Devices/{device_id}
  body: {
    jamf_managed_id:    jamf_lookup.managementId,
    enrollment_status:  'enrolled',
    policy_applied:     true
  }

// ============================================================
// AGENT HANDOFF 1 → 2 — Asset Register Agent to Comms Agent
// Trigger: Airtable record status set to 'assigned' AND enrollment_status = 'enrolled'
// ============================================================

// ============================================================
// AGENT 2 — Device Lifecycle Comms Agent
// ============================================================

// Step 7: Send assignment confirmation via Gmail
gmail_send = Gmail.POST /gmail/v1/users/me/messages/send
  body: {
    to:       airtable_record.assigned_to_email,
    subject:  'Your device is ready — ' + airtable_record.serial_number,
    template: 'device_assignment_confirmation',
    fields:   {
      assigned_to_name:  employee_name,          // looked up from Airtable Staff table
      serial_number:     airtable_record.serial_number,
      assignment_date:   airtable_record.assignment_date,
      expected_return:   airtable_record.expected_return,
      policy_link:       config.acceptable_use_policy_url
    }
  }
// Returns: gmail.message_id — written to airtable_record.comms_log

// Step 8: Post summary to IT Slack channel
slack_post = Slack.POST {it_ops_webhook_url}
  body: {
    text: ':white_check_mark: Device assigned',
    blocks: [
      { type: 'section', fields: [
        { label: 'Employee', value: airtable_record.assigned_to_email },
        { label: 'Serial',   value: airtable_record.serial_number },
        { label: 'Jira',     value: jira_ticket.key },
        { label: 'Return by', value: airtable_record.expected_return }
      ]}
    ]
  }
// Returns: slack.message_ts — written to airtable_record.last_comms_sent

// ============================================================
// RETURN / OFFBOARDING PATH
// Trigger: inbound_event.event_type = 'offboarding_return'
// ============================================================

// Agent 1 sets airtable_record.status = 'pending_wipe'
// Agent 3 fires on 'pending_wipe' status change

jamf_wipe = Jamf.POST /api/v1/preview/mdm/commands
  body: {
    commandType: 'ERASE_DEVICE',
    managementIds: [jamf_lookup.managementId]
  }
// Returns: { commandUuid, status: 'Pending' }

Airtable.PATCH -> wipe_status: jamf_wipe.status   // 'Pending'
// Status remains 'pending_wipe' until IT Coordinator manually sets to 'available'
// That manual update triggers Comms Agent restock alert to #it-ops

// ============================================================
// QUARTERLY AUDIT PATH
// Trigger: scheduled cron every 90 days at 08:00 UTC
// ============================================================

// Agent 2 reads Airtable view 'all_active_assignments'
// Sends 'quarterly_audit_request' template to each assigned_to_email
// Embeds Airtable form URL for structured confirmation response
// Form responses write directly to Airtable audit_confirmed field
// Non-responses after 5 days trigger 'overdue_audit_reminder' email

// ============================================================
// ERROR LOGGING (all agents)
// ============================================================
Supabase.INSERT INTO automation_error_log {
  agent_name:   string,
  error_type:   string,
  serial_number: string | null,
  payload:      jsonb,
  ts:           timestamptz
}
Developer Handover PackPage 3 of 4
FS-DOC-04Technical

04Recommended build stack

Orchestration layer
A workflow automation tool running one workflow per agent (three workflows total): 'asset-register-agent', 'device-lifecycle-comms-agent', and 'mdm-sync-agent'. All three workflows share a single credential store so Airtable, Jira, Gmail, Slack, and Jamf tokens are managed centrally and rotated in one place. Each workflow is version-controlled and deployed to a dedicated environment (staging and production).
Webhook configuration
Jira outbound webhook: configured on the IT project to fire on issue_created and issue_updated events. Filter: project = IT AND issuetype in (new_hire_device, offboarding_return, device_request). Payload includes issue.id, issue.key, issue.fields.assignee.emailAddress, and all relevant custom fields. HR webhook: POST endpoint exposed by the automation platform, secured with HMAC-SHA256 signature verification using a shared secret supplied by the HR system. Google Sheets fallback: a scheduled polling step runs at 07:00 UTC daily and reads new rows from a named sheet tab ('IT_Events') using the Sheets API v4.
Templating approach
All Gmail message bodies are stored as HTML templates in the automation platform's template store. Three templates are required at launch: 'device_assignment_confirmation', 'quarterly_audit_request', and 'overdue_return_reminder'. Dynamic tokens use double-brace syntax matching the Airtable field names (for example {{serial_number}}, {{assigned_to_name}}, {{expected_return}}). Template updates are made in the platform without redeploying the workflow. Slack messages use Block Kit JSON stored inline in the workflow step, with field values injected at runtime from the Airtable record.
Error logging
All agent errors are written to a Supabase table named 'automation_error_log' with columns: id (uuid, auto), agent_name (text), error_type (text), serial_number (text, nullable), payload (jsonb), ts (timestamptz, default now()). A Supabase database webhook or row-insert trigger fires a Slack alert to the #it-ops channel whenever a new error row is inserted. The IT Coordinator receives a Gmail digest of all unresolved errors at 09:00 UTC each weekday. Error rows are retained for 90 days before automatic deletion.
Testing approach
All three agents are built and tested against sandbox credentials before any production data is touched. Airtable sandbox: a duplicate base named '[STAGING] Devices' with ten synthetic device records. Jira sandbox: a test project (key: ITS) with matching issue types. Jamf sandbox: the Jamf sandbox environment provided under the Jamf Pro subscription, isolated from managed devices. Gmail sandbox: a test Gmail account (it-automation-test@yourcompany.com) used for all outbound send tests. Slack sandbox: a private test channel (#it-automation-test). Integration to production credentials occurs only after all test cases in the QA plan have a passing status.
Estimated total build time
Asset Register Agent: 14 hours. Device Lifecycle Comms Agent: 8 hours. MDM Sync Agent: 12 hours. End-to-end integration testing and QA: 2 hours (included in the 36-hour total from the snapshot). Total: 36 hours across a 5-week delivery schedule.
Before build kickoff the following must be confirmed: (1) Airtable base ID and table schema match the field names documented in this pack; (2) Jira project key and custom field IDs for serial_number_cf and expected_return_cf are provided; (3) Jamf API service account is created with the minimum scopes listed in the MDM Sync Agent specification and the instance URL is accessible from the automation platform's outbound IP range; (4) Gmail OAuth consent is approved for the shared IT account; (5) Slack webhook URLs for #it-ops and IT Manager DM are generated and stored in the credential store; (6) Supabase project is provisioned and the error_log table is created. Contact the FullSpec team at support@gofullspec.com to confirm these prerequisites before the build kickoff date.
Developer Handover PackPage 4 of 4

More documents for this process

Every document generated for Device & Hardware Management.

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