Navigate and extract data from the Dedalus enterprise Workday tenant
(https://wd3.myworkday.com/dedalus/d/home.htmld) through the browser,
reusing the user's live authenticated session.
Prerequisites
- Node.js: required — https://nodejs.org
- playwright npm package:
npm install playwright.npx playwright installis not needed —connectOverCDPattaches to the user's existing browser and downloads no browser. - The user's own browser (Chrome / Brave / Edge — all Chromium), already logged into Workday via SSO. You will relaunch their real profile with a debug port (never a fresh profile). See the connect section below.
Golden rules
- Never log in. Auth is SSO/MFA and owned by the user. Reuse their real
browser profile (see connect below) — do not automate the login page and do
not spin up a fresh
--user-data-dir(that forces a new SSO/MFA login). - Select by
data-automation-id. Workday CSS classes are generated and unstable;data-automation-idattributes are stable. Prefer[data-automation-id="..."]over class or text selectors. - Reconnaissance first. The tenant UI is in French and configuration
varies. Screenshot + dump
data-automation-ids before acting; match both French and English labels (see reference files). - Read-only by default; writes are gated. This is sensitive HR/PII data. Extract and report. Never submit a form, request, or approval without explicit user confirmation — always preview the exact items first (see time-validation.md). Do not persist PII.
- Wait for the SPA. Workday is a heavy single-page app. Always
waitForLoadState('networkidle')and wait for a targetdata-automation-idbefore scraping; let spinners disappear. - Verify authentication. SSO can silently expire mid-session and bounce to
Microsoft /
wd3-identity.myworkday.com//authgwy//pending=trust(incl. a "Mémoriser ce périphérique ?" screen). Treat those URLs as NOT_AUTHENTICATED and callassertAuthenticated(page)at the top of every recipe (see automation-snippets.md).
Connect to the authenticated session
Reuse the user's real profile so the live SSO session carries over — the
objective is "never log in". Because --remote-debugging-port can't be added to
a running browser and a fresh profile forces a login, the flow is: close the
user's browser (Chrome/Brave/Edge), relaunch the same --user-data-dir with
--remote-debugging-port=9222, then chromium.connectOverCDP(...) and open
Workday in a new tab. Windows/PowerShell + macOS/Linux commands, per-browser
profile paths, CDP diagnostics, and the assertAuthenticated helper:
reference/automation-snippets.md.
Navigation model
Prefer search-driven navigation over clicking menus — it is the most robust path across configs. Open global search and type the task/report name:
- Balances →
Solde d'absences/ "Time Off Balance" - My team's leave →
Absences de mon équipe/ "My Team's Time Off" - Request →
Demander une absence/ "Request Absence" (confirm before submit)
Full navigation map (home, apps/worklets, menu, profile, search selectors) in reference/navigation.md.
Task index (the tools this skill provides)
| Goal | Recipe |
|---|---|
My leave/RTT balance (solde) |
absence-recipes.md |
| Request congés / RTT | absence-recipes.md |
| Team time-off per day / week | absence-recipes.md |
| Who is off today (team) | absence-recipes.md |
| Team roster / org data | navigation.md |
| Org chart / organigramme | navigation.md |
| Validate/approve team time & absences (write) | time-validation.md |
| Inbox summary — "Mes tâches" (what's waiting on me) | reports-payslips.md |
| Payslips / bulletins de paie | reports-payslips.md |
| Run & export any Workday report; balance forecast | reports-payslips.md |
| Scrape a Workday grid / export | automation-snippets.md |
Workflow
- Reuse the user's real profile (close → relaunch same
--user-data-dir+ debug port), attach via CDP, open Workday in a new tab, and confirm the home loaded (networkidle, home worklets visible). - Call
assertAuthenticated(page); if bounced to SSO, let the user complete it. - Take a reconnaissance screenshot and dump visible
data-automation-ids. - Navigate to the target task via global search using the label variants.
- Wait for the result grid/panel, scrape by
data-automation-id(fall back to<tr>scraping for virtualized grids), or use "Export to Excel" (with the async-export fallback) for tabular data. - Return structured results (JSON/table). For per-week views, aggregate rows by ISO week; for per-day, group by date.
Examples
"Combien de RTT il me reste ?" → search "Solde d'absences" → read RTT row.
"Qui est en congés dans mon équipe cette semaine ?" → "Absences de mon équipe"
→ prompt dialog → OK → scrape rows → cross-check vs roster → names by day.
"Qu'est-ce qui attend ma validation ?" → open "Mes tâches" → summary by type.
"Montre l'organigramme de mon équipe" → "Mon organigramme" → parse node text.
Important Notes
- Tenant is fixed:
dedalusonwd3.myworkday.com. Never hardcode other tenants. - The inbox is "Mes tâches", opened from the header tray icon
(
inbox_preview). The URL.../d/inbox404s — never use it. - Team time/absence data does not flag presence directly: derive present/absent by cross-referencing the roster (missing worker ≠ absent), netting ±1 RTT pairs, and treating public-holiday gaps as holidays, not absences.
- Labels are French first; keep English fallbacks from the reference files.
- If a page renders inside an iframe, switch to
page.frameLocator(...)first. - Manager-only reports (team time-off) require the user to be a people manager.