Process · medium — approve timesheets
The case. The manager chooses the timesheets to approve, then confirms. The HR tool expects a list of identifiers.
What the example shows. A part that is a set (countable: false), lines sent as
identifiers (line_shape: ref), a write separated from the reads, the manager's confirmation as
the act.
examples/actuelle/process-medium.yaml
# Process · medium — a manager approves timesheets. A SET, not a basket: each timesheet once,
# sent to the tool as a list of ids. The manager's confirmation is the act.
station:
id: validation-heures
name: Validation des heures
global:
language: fr
currency: EUR
locale: fr-FR
domain:
domain_type: saas
entity_name: feuille d'heures
entity_name_plural: feuilles d'heures
agent:
tone: professional
name: Validation des heures
persona: "un assistant qui prépare les validations du manager, sans jamais décider à sa place"
rules:
- "Ne jamais valider une feuille que le manager n'a pas choisie."
emoji: false
portals:
web:
widget:
origins: [https://heures.example.fr]
apis:
- name: rh-lecture
openapi_url: https://rh-api.example.fr/openapi.json
base_url: https://rh-api.example.fr
operations:
- {id: getTimesheets, access: read}
- {id: getOvertimeReport, access: read}
auth: {type: api_key, key_name: X-RH-Key, key_location: header, key_env: RH_READ_KEY}
- name: rh-ecriture # the write, separated so the boundary is visible
openapi_url: https://rh-api.example.fr/openapi.json
base_url: https://rh-api.example.fr
operations:
- {id: approveTimesheets, access: write}
auth: {type: api_key, key_name: X-RH-Key, key_location: header, key_env: RH_WRITE_KEY}
skills:
- name: feuilles
cognitive:
objective: "lister les feuilles d'heures en attente pour que le manager choisisse celles à valider"
diagnose: [l'équipe, la semaine]
invoke: {method: getTimesheets}
kinds: {feuille: {}}
present: # no price: nothing is sold here
fields:
name: {from: name, type: text, role: title}
countable: false # "3 × the week of Awa" is not a thing
submit:
- name: approve
mode: request
tool: approveTimesheets
line_shape: ref # the tool takes timesheet_ids: list[str]
args:
body.timesheet_ids: "$selection[kind=feuille]"
body.idempotency_key: "$action.key"
render: {component: cards}
- name: rapport-heures-sup
invoke: {method: getOvertimeReport}
render:
component: report
report:
headline: total_overtime_hours
headline_label: "heures supplémentaires"
unit: h
submit_guard:
confirm: true # the manager's own click files the approval
What happens
| step | Core | result |
|---|---|---|
| "my team's pending timesheets" | feuilles → getTimesheets | cards, one per timesheet |
| three timesheets chosen | set: no quantity | three lines, no −/+ button |
| "Approve" + confirmation | approveTimesheets with timesheet_ids: [...] | receipt in the room |
| the agent tries to approve on its own | confirm: true | refused without the manager's click |
Key points
countable: falseis about the selection;line_shape: refis about the tenant. Both are needed, and Core refusesrefon a part that has quantities.- Limit today: the
RH_WRITE_KEYkey is the station's. Two managers approve under the same identity, for the HR tool. Only deploy this case if a single manager uses it, or wait for per-person identity (target version).