Discover before configuring
GET /api/v1/workforce/discovery and the MCP tool atlas_discover_workforce call the same native read. Supply from, to and as_of ISO instants; the observation window is at most 31 elapsed days. view=summary returns exact Queue, Agent-slot and membership counts plus source states and unresolved decisions. view=queues or view=people returns at most 100 detail records using offset and limit; optional search filters by display name after Atlas count-checks the complete canonical population. An incomplete read returns a failure rather than a partial inventory labeled complete.
The source facts distinguish configured routing membership, opt-in, provider team, supervisor and skill evidence, observed handling, derived presence, provider service-goal assertions and approved Atlas policy. Supervisor assignments do not grant Atlas roles; skill IDs remain provider routing evidence and never grant Atlas Work Qualification. A missing skill snapshot is unknown, not an empty skill set. An exactly identified Queue may show its observed offered-work total, but that aggregate does not prove interval completeness or forecast readiness. Provider business-hours and closure references do not prove the full dated calendar definition. A newer provider hours notice marks an older adopted Atlas calendar as stale; preview and confirm the native calendar update through the existing importer. Missing activity mappings or Person links remain unavailable/unresolved. This operation creates no WFM configuration. Provider identity, semantic demand and Person detail require their separate token grants and current native authority; a workforce grant alone does not expose those sections.
tools/list, then invoke it on /api/mcp with the same token’s MCP transport grant:
api:connect or current schedule authority is a 403 REST error. An archived activity source is an explicit unavailable section rather than zero presence. A changing or capped inventory fails the read; retry after source stabilization. REST errors use {error:{code,message}}, and MCP returns the same code in a structured tool failure.
Review and configure a workforce
Admin → Workspace setup → Workforce setup begins with this deterministic discovery. The existing Atlas native agent must read the same inventory before preparing a setup plan. It may inspect only a named gap, then submits the existing structured preview with supported changes or exact blockers. The discovery read does not create a group or publish a schedule. Existing saved setup plans remain readable under current source permissions. Applications and external agents can perform the same setup throughPOST /api/v1/workforce/setup/preview / atlas_preview_workforce_setup, forecast-group publication, scheduling-group creation and dated membership creation. Each mutation rechecks current native authority and attributes its effect to the token Actor. Forecast-group publication additionally requires mcp:schedules:publish alongside mcp:schedules:write, including when invoked through saved-assessment apply; the native transaction rechecks the stored grant. No new credential, setup ledger or agent runtime is required.
Preview accepts at most 20 recommendations and 100 total proposed members, under shared compute admission. A forecast configuration always requires horizonDays, even when demand is null. Targets must match the exact work scope, reporting timezone and effective period. A scheduling recommendation may name another recommendation’s forecastGroupKey; its returned command binds that exact forecast publication. Apply the forecast first. A queue is not required to belong to exactly one forecast group, but the same work units are never forecast twice. A proposed forecast whose scope equals an active Forecast Group’s is refused as forecast_group.duplicate_scope: <id>, naming the group to reuse. One that is a slice of an active group’s work units, or of another proposal’s, is refused as forecast_group.scope_overlap: <id or key>: a slice with no planning distinction belongs in semantic reporting, and one with a distinction needs a partition or demand binding rather than a second additive forecast. Scopes on different filter dimensions are not claimed to overlap. A Forecast Group the forecast-group cutover created from a scheduling group’s manual demand without a queue keeps the all-queue scope (objectType queue, objectId null), which contains every queue scope: publish a narrower revision of it, or reuse it, before setup proposes a forecast for one of its queues. Proposed demand bindings are also checked against each other as they would be saved, so two proposals that bind the same demand additively, mix interpretations or exceed it with partition minimums are both refused with the conflict and the other proposal’s key.
Discovery groups queues whose provider service goal, hours, routing and active members’ routing skills all match into an equivalent_queues question. It suggests one Forecast Group that keeps each Queue as a dimension, or reuse of a group one of them already has (proposedValue.reuseForecastGroups). It never merges queues, and any unknown or differing evidence, such as a language skill, keeps them apart.
Retain the returned commands, including their keys and source fingerprints. Group creation links the group and native object in one transaction. Membership creation provisions any needed native Agent slot in the same transaction as its dated membership; an assignment/FTE/overlap failure leaves neither partial effect. Existing overlapping membership is refused, not silently edited. Assignment enforce mode cannot be bypassed with a Person-only request.
When a reused Agent occupancy is employment-linked, membership must explicitly name that employment assignment, including in a legacy workspace. A Person-only request returns workforce.member_assignment_required (422) instead of losing the assignment context and leaving a roster that cannot commit shifts. Inspect the effective assignment and submit a new reviewed request.
createReady describes configuration validation. operationalReadiness: not_verified remains until source, qualified roster, demand and draft checks succeed. Membership eligibility is rechecked at commit. Successful configuration does not claim a forecast, executable schedule, customer activation or later service improvement.
For an assessment saved by the native agent, POST /api/v1/workforce/setup/apply / atlas_apply_workforce_setup selects only {sessionId, resultRef, key, memberRequestKey?}. The backend loads the exact saved command; callers cannot replace its configuration. A new correction prevents uncommitted effects from the old result. Already committed requests remain recoverable using the original selector and current authority. Each item is an independent authorized effect, so partial completion is explicit.
The requested historical window is retained as {start, end, timezone} and is limited to 366 elapsed days. It does not imply complete observations or change a source’s grain. The setup page issues the assessment through the existing Agent Kernel with reads only, retains corrections in that conversation, and lets the operator reopen their saved work. GET /api/v1/workforce/setup/assessments / atlas_list_workforce_assessments lists at most ten of the issuing Person’s own sessions executing in the selected workspace; it returns no conversation history or titles from other workspaces. External agents can independently discover sources, invoke the same native preview and apply its exact commands through the paired REST/MCP operations.
Use GET /api/v1/workforce/configuration-results/{requestKey}?kind=group|member|forecast_group or atlas_inspect_workforce_configuration after uncertainty. A saved receipt confirms the native effect. A failed read leaves the outcome unknown; a null response is no confirmed receipt and does not prove an in-flight request failed. Reuse the original key rather than create another. An unrelated same-name group is never treated as a successful retry.
External creation and recovery example
In an authorized test workspace, retain one UUID inREQUEST_KEY. The connection needs explicit api:connect, workspace scheduling write scope and the issuer’s current manage_schedules capability. Membership additionally requires manage_workforce_roster.
/api/mcp with the bearer credential, Accept: application/json, text/event-stream and the negotiated MCP protocol version. A changed body under the same key returns workforce.operation_conflict. A superseded review returns workforce.assessment_superseded. Missing transport or current native grants return 403; unavailable commit/read acknowledgement returns an unknown outcome (503). No browser cookies are used. Older MCP group/member argument forms remain accepted, but callers must supply or retain the returned request key for safe recovery.
Credentials
In Settings → MCP connections, create an integration with explicit REST access. REST requiresapi:connect on the existing atlas_mcp_ connection. Existing keys gain no implicit REST permission. Scheduling reads require workforce workspace grants and current manage_schedules authority; effects also require the workforce write grant. Provider reads retain separate provider grants and current provider setup authority.
Explicit integrations default to 90 days. A narrowly scoped single-workspace planning connection can explicitly expire only when revoked. Ordinary MCP defaults remain seven days. Rotation shows the new secret once and atomically revokes its predecessor. Both transports recheck current issuer authority and attribute effects to the token Actor. Browser cookies, caller identity fields, and atlas_ingest_ scheduling credentials are refused. OAuth is not implemented by this contract.
Renewable integrations can explicitly include mcp:schedules:publish for reviewed forecast-group publication and mcp:semantic:read with its workspace selector for setup evidence. These grants are not implicit, and current native authority is checked on creation, rotation and invocation. Until-revoked planning keys exclude both grants; use a renewable connection when setup needs them.
Complete or reconcile pending issued draft requests before rotating a connection. The successor has its own token Actor and cannot inspect or commit requests issued by the revoked predecessor; existing source receipts remain available to authorized native users.
Configured planning
Availability, preferences, daily and weekly patterns, rotations, activity obligations and demand bindings are native configuration on their existing owners. The signed-in product,/api/v1/workforce and MCP call the same typed operations; transports differ only in how identity is established.
Every write takes a retained UUID: the REST
Idempotency-Key, or request_key through MCP and the signed-in product. An unchanged retry returns the recorded result and a changed body under the same key conflicts. Archive, withdrawal, resolution and assignment end also replay from their recorded state. After a lost response, read the record (profile, change, pattern, binding or assignment) before an unchanged retry.
Self-service and manager authority
In Settings → MCP connections, a custom connection can include My schedule:mcp:self:read with the mcp:self:workspace:<workspace> selector, and optionally mcp:self:write. Each request rechecks the issuer’s current view_own_schedule, and writes their current manage_own_scheduling_preferences. The Person always comes from the connection or session; caller identity fields are refused. Self operations change only availability and scheduling preferences, never contract, qualification or manager terms, and they never list another Person’s profile. They do not use manage_schedules.
Manager operations require the workforce workspace grant (and the write grant for effects) intersected with current authority: manage_scheduling_profiles for the exact Person or Assignment, manage_rotations for patterns and assignments, and manage_schedules for the Scheduling Group of a binding. Reads never provision an Actor or mutate configuration.
An employee change becomes an effective revision unless the availability it submits conflicts with published commitments, falls below a contract minimum or has impact that could not be assessed; those stay pending_review. A preference-only change always applies directly, whatever the unchanged availability shows. Pending changes never affect planning.
A change takes effect today unless it names validFrom. A second change on the same day replaces the first, which stays in the revision history with an empty range (validTo the day before validFrom) and never governs a date. Preferences can also take effect ahead of a revision scheduled for a later date: that revision keeps its own terms and takes the new preferences unless it schedules its own. Other terms start on or after the latest revision’s start date; an earlier date is refused with the scheduling-profile.invalid_supersession_date issue (422). Each save still names the revision it was based on (scheduling-profile.stale_revision, 409), and an unchanged retry returns the recorded revision.
A pending change is reviewed through the existing approval owner, as for time off and shift swaps. It is a scheduling_profile_change object record that the workspace’s published decision policies evaluate when it is submitted. Workspace provisioning seeds an editable “Scheduling change review” starter that routes every such change to wfm_manager_role. Admins can branch on the published_commitment_conflict, below_contract_minimum and impact_incomplete facts. The routing creates an approval request and its Inbox item. The submission returns routing:
routed: an approval request and Inbox item exist.not_configured: no published policy routes the change.routing_pending: evaluation was incomplete. An unchanged retry routes it again.
reviews with their approval request IDs and status. A routed change resolves only through its review. The approvals rail, or the paired resolve operation, approves or rejects it in the same transaction as the review. That transaction requires the routed reviewer role and current manage_scheduling_profiles authority over the change’s subject. It rechecks the revision the change was based on (scheduling-profile.stale_revision, 409), closes the change’s other pending reviews and closes the Inbox item. The employee withdraws a routed change by cancelling its review. The native resolve and withdraw commands refuse a routed change with scheduling-profile.review_in_progress (409). Only a change that no policy routed is resolved directly by a manager with current authority. Employees cannot review their own changes, and no authority grant resolves a change without a person.
An approval or rejection of a reviewed change, whether through its review or the direct resolve, reaches the employee as an Inbox item (“Your scheduling change was approved” or “declined”) with Inbox’s usual notification delivery. A withdrawal sends no notice. The employee reads the outcome through GET /me/scheduling-profile/changes or atlas_list_my_scheduling_changes: status, resolvedAt, resolutionNote and each review’s status. A notice that could not be handed over is retried by the approval delivery sweep, never by repeating the decision.
The private note on a change is visible to its author and to reviewing managers only. Roster, approval, Inbox, assistant and list projections omit it, and so does the decision notice.
Availability and preferences
Availability is explicit:unknown, unrestricted or restricted. A restricted declaration has weekly rules (closed, or several non-overlapping windows per day), dated exceptions and the IANA zone its wall times were declared in. Profile validity and exception dates are civil dates; window times are wall times in the declared zone; resolved intervals are UTC instants and survive DST. Person-wide restrictions apply to every Assignment; an Assignment profile can only narrow them, and a contradiction is returned with both sources. The other profile terms resolve the same way, field by field: a Person-wide weekly limit caps all of the Person’s work and an Assignment limit caps that Assignment’s work, shift-length bounds from both scopes intersect, and an Assignment that leaves a field empty inherits the Person-wide restriction instead of discarding it. Bounds that leave no shift length are a profile.shift_bounds_contradict contradiction. Only effective revisions take part; a pending employee proposal never does. A dated exception changes only its date and scope; it never removes leave, contracts, qualifications or other commitments. Observed login time is never a declaration.
A missing profile, an unknown declaration or an omitted weekday is unassessed. Autonomous generation and rotation exclude unassessed time and report it; they never assume all-day availability. When assessed time on a date admits none of a Person’s permitted shift starts and lengths, generation reports availability.no_permitted_shift for that date instead of leaving a silent gap. Manually edited, copied, rotated and published schedules meet the same hard constraints as generation: a shift in time an explicit declaration excludes is blocked (availability.outside_declared_availability), as is a shift length outside the resolved profile bounds, a required activity that is missing, shares its only placement with another required activity, or breaks its order, separation or contiguous-work limit, and a weekly pattern maximum the schedule breaks in a week it works (counting published commitments). Unassessed time keeps its historical manual meaning; only autonomous planning excludes it. Legacy one-window profiles stay readable; once a structured declaration exists, a legacy availability edit is refused rather than silently ignored.
Preferences (startWindows, finishWindows, shiftLengths, workingDays, ranked daysOff, ranked weeklyPatterns) are soft. Absent preferences cost nothing. Each satisfied or unmet preference is normalized by its stated strength or rank and reported with its denominator; a strong preference never overrides a hard rule. Explanations name the preference kind, not personal reasons.
A start window carries a strength, or a rank when the windows are ranked start choices (“1st choice 08:00, 2nd choice 09:00”). Each workday’s start then scores one item weighted like a moderate preference: the n-th of that day’s choices in rank order satisfies 1/n, and a start outside all of them satisfies 0. Ranked and strength-weighted windows cannot apply to the same day, and choices that share a day need different ranks. A finish window (days, earliest, latest, strength) is read at the shift’s local finish in the preference zone, so it holds across a DST change; its days select the workday the shift starts on, and a finish at midnight meets a window that ends at 24:00. Unmet finish windows are reported as preference.finish_window_unmet.
Patterns, obligations and accounting
Adaily pattern bounds starts (earliest, latest, incrementMinutes; a fixed start sets them equal), durations (a range with an increment or explicit options), its zone basis, applicability, eligible work, an optional declared split, and required activities. A weekly pattern lists eligible daily patterns per day with workday, hour (with an explicit basis), rest, consecutive-day and consistent-start bounds; weeks start on Monday in the planning zone. A rotation orders weekly patterns from the assignment’s anchor week. Four ten-hour days and five eight-hour days can be assigned to different people in one roster. A personal assignment narrows the alternatives without removing mandatory rules, and adjacent published commitments count toward rest, weekly hours and consecutive days.
An activity obligation has a type, shift-length trigger, duration, a shift-relative or wall-clock window, precedence and ordering, minimum separation, contiguous-work limit, recurrence, eligible qualifications and movement (movable, deferrable, cancelable or protected). Generation places required activities while it evaluates each candidate, so a permitted meal move can improve productive coverage. A required activity with no permitted position is a activity.required_infeasible contradiction or a search limit, never a dropped activity. Breaks, meals and other required activities come only from an authored pattern, including one applied from a reviewed setup recommendation. Atlas never chooses employer obligations itself: a historical fixed-window rotation, or a generated shift with no authored pattern, carries no breaks or meals, and the result reports activity.policy_not_configured for those days. Protected and generated blocks remain locked through rotation, copy and edit validation. A span edit, move or published change that would cut or drop a protected block is refused whole with schedule.protected_activity_outside_shift (422 in the schedules workspace); a move leaves the block at its fixed time. A derived time-off projection still re-clips with its shift.
Elapsed, paid, contract-counted and productive minutes are separate. An 8.5-hour span with an unpaid 30-minute meal and two paid 15-minute breaks is 8 paid and 7.5 productive hours, and 6.75 expected productive hours after an assessed 10% residual loss applied once. Contract hours follow the pattern’s contractBasis. Issued proposals cite the exact pattern revision. Archiving keeps history and returns current usages.
Demand bindings and shared plans
A binding makes a Scheduling Group eligible to supply a Forecast Group’s demand; it never copies the demand. Overlapping additive bindings of one Forecast Group are refused unless they declare apartition with share bounds, a shared_pool, or distinct sequential_stage keys. The group’s default_forecast_group_id remains the zero-or-one adapter while no explicit binding exists. One requirement row per Forecast Group scope is owned by one supplying group. Each sequential stage is its own scope with its own requirement and suppliers, and carries stage_rollup_counts_each_stage: a total across stages counts an interaction once for every stage it passes through. A binding’s qualification_ids restrict who supplies its demand to people qualified at that time; a Person whose groups supply only qualification-gated demand they cannot work on a date is excluded with work_qualification.not_qualified_for_demand.
Partition shares add up only on the dates they share: totals are checked on each segment between effective dates, so a dated replacement never counts alongside the binding it replaces. Minimum shares above the whole demand are refused (demand_binding.partition_exceeds_demand); maximum shares that stop short of it are a warning (demand_binding.partition_incomplete), because a split is bound one supplier at a time. In planning, a fixed share (minimum equals maximum) is that group’s own obligation: only its people supply it, and it can be planned alone. Flexible bounds keep the whole obligation, so every supplier must plan together: each supplier’s minimum is its own and the rest is shared. Generation refuses a flexible partition rather than approximating it when a supplier is missing from the plan (generation.partition_requires_participants), when a supplier could pass its maximum by taking all of the shared rest (generation.partition_bounds_unsupported), or when the bounds change within the period (generation.partition_change_unsupported).
Issue a shared draft with target: {participant_group_ids, period_start, period_end} (2–10 groups). The 14-date and 200-roster limits apply to the complete scope. One physical timetable allocates each Person’s time once across groups and scopes; channel concurrency changes throughput, not human time. Commit writes one draft Schedule per participating group atomically, rechecks every participating source revision, and refuses a shift that overlaps the same Person’s work in any other schedule. Single-group plans treat that work, including other drafts, as occupied time, so two concurrent drafts cannot double-book a Person.
Objectives and results
Hard rules are enforced first. The declared objective then minimizes coverage shortfall by scope and interval, then preference penalty, then maximizes placed minutes and balances workload. Ties prefer the earlier start, the shorter length, fewer weekly minutes, then the Person id. Cost is unavailable unless authorized compatible cost inputs exist. A proposal returns its objective, score components,contradictions (proved input conflicts), searchLimits, exclusions with reasons, policyGaps and coverage shortfall. A search limit says where the bounded search stopped without deciding, never that an alternative is infeasible: planning.activity_search_limit when activity placement ran out of evaluations, planning.shape_lengths_sampled when a profile allows more hourly shift lengths than the search evaluates (the message names the sampled step), and planning.improvement_search_limit when local improvement reached its move or pass bound while moves were still improving the plan. Supply is evaluated between consecutive event boundaries (shift and activity edges, commitments, absences, service windows, memberships and qualifications), so time inside a forecast interval when nobody works is a shortfall and is never averaged away. Coverage is reported at the forecast’s own grain: each interval carries its original requirement, its average supplied, its lowest minimumSupplied, the integrated shortfall and inProtectedActivities, the average number of the proposal’s suppliers held in protected meetings or accommodations, which explains the shortfall protection leaves. A constraint-valid draft with unmet demand stays useful and shows its shortfall; hard violations cannot be committed. A weekly pattern maximum is a hard conflict in any week the proposal adds work to, even when earlier commitments already reached it; a week it leaves untouched is evidence. Generation and rotation proposals return the same finding lists, and the schedules review dialog and the assistant’s draft tool show them before anything is applied: hard conflicts, which keep the proposal from being applied, contradictions, search limits, exclusions, weekly pattern evidence and policy gaps.
Source and calculation contract
- Read
/api/v1/workforce/discovery/atlas_discover_workforce, then/readinessif configuration-only evidence is needed. Exact counts distinguish empty configuration from failed reads.queue_settingsnow pages all active queues and preserves provider service-goal units and dates. Missing, conflicting, sensitive or unavailable values are not defaults. These settings are configuration evidence, not observed performance or proof of current provider delivery. Provider discovery and sync receipts retain their separate grants. - Inspect
/connections, inventory, sync status and calendar preparation. These reuse existing provider operations. Retained inventory alone does not prove current delivery; missing receipts remain unknown. - Inspect
/scheduling-groupsand/scheduling-groups/{groupId}. Confirm the existing dated roster, calendar and demand configuration. This API does not guess assignments or silently configure customer workspaces. - Read or compute requirements, then issue, inspect and commit a native draft request.
prediction_not_ready with a next action; obtain completed evidence through the existing forecast workflow before retrying.
residual_unplanned_shrinkage is an explicit fraction from zero up to, but excluding, one. It is the loss remaining after scheduled nonproductive activities. Zero explicitly assumes no additional unplanned loss; it is not inferred from total shrinkage.
New calculations retain exact net demand beside existing gross requirements. Productive coverage compares productive supply adjusted by residual loss with exact net demand over UTC event boundaries. Historical gross rows remain readable, but absent net evidence or an unassessed residual is unavailable for productive coverage decisions. Native callers that omit residual retain exact net without silently choosing zero; a recomputation with an explicitly assessed residual is required for coverage-backed leave approval. Missing-only evidence is reported as state: "unknown", assessment: "not_assessed", with null demand facts. Automatic approval remains blocked. An authorized human manager may use the existing native manual override with a reason; the receipt retains that coverage was not assessed. Invalid or stale evidence and unavailable qualification remain blocked. Rounded gross counts cannot reconstruct net demand. JS and PostgreSQL normalize derived gaps within 1e-9 people of zero to zero, keeping source evidence unrounded. Configured planning (configured-plan-1, shared-plan-1) scores qualified productive time, after scheduled activities and the assessed residual, against exact net demand and places required activities inside candidate evaluation; see Configured planning. It remains a bounded deterministic search: it reports proved input contradictions separately from search limits and never claims global infeasibility. Requests issued under an earlier calculation remain inspectable and their committed results replay. An uncommitted one is refused as generation.source_changed and must be refreshed, so every commit runs the configured-plan checks.
REST example
Read the native Intraday snapshot withGET /api/v1/workforce/scheduling-groups/{groupId}/intraday?date=YYYY-MM-DD or MCP atlas_get_workforce_intraday with workspace_id, group_id and optional date. The date defaults to the scheduling group’s local today. Both use the same IntradayService and snake-case response as the native board, including published schedule references, canonical activity, adherence, interval observation metadata and forecast/actual comparisons. The existing workforce workspace grant and current transport authority apply; the issuer must additionally have view_workforce_actual_activity. Raw provider status and substatus require view_workforce_activity_raw.
intervals[].observation separates elapsed and remaining interval time, source observation and stabilization cutoffs, and provisional/final person-time status. forecast_actuals retains the forecast’s original interval grain and timezone. Its full-interval forecast and actual so far are separate values; the live read never writes or finalizes prediction actuals. Unknown source completeness remains explicit. Use history=deferred in REST or include_history=false in MCP for the native deferred-history mode. Existing refresh requests see newly ingested facts without initiating a provider collection.
Use actual authorized identifiers and retain UUID operation keys before sending. Environment variables below keep credentials out of command literals.
POST /api/v1/workforce/scheduling-groups/{groupId}/requirements/compute, the same bearer/workspace headers, Content-Type: application/json, and Idempotency-Key: <compute UUID>:
POST /requirements/evaluate takes the date range and residual fraction but neither starts inference nor persists requirements.
Issue with POST /api/v1/workforce/draft-requests, a new retained Idempotency-Key, and:
GET /draft-requests/{requestKey} before POST /draft-requests/{requestKey}/commit with the same Idempotency-Key and no body. Commit rechecks current authority and source revisions, then creates a draft; publication remains separate. Identical retries through either transport return the native receipt. After a stale-source conflict, obtain and review a new proposal.
The setup page continues from verified scheduling configuration into these same operations. A scheduling recommendation can retain review.planning with {from,to,timezone,residualUnplannedShrinkage,basis,evidenceRefs}. It requires 1–14 inclusive dates, the scheduling group’s timezone, a residual fraction in [0,1), an explanation and retained source references. The native agent validates its cited references. Both external setup preview and assessment reads use the same additive contract. Proposed inputs are analysis, not a new source authority or permission to commit.
The draft form uses those proposed inputs without asking the operator to reconstruct them. Missing planning evidence blocks the initial calculation and links back to Atlas; an operator may explicitly enter their own inputs. Calculate staffing, review the proposed shifts, then commit. The page retains operation keys across reloads in the current browser tab and rereads the current draft against the receipt and reviewed shifts. A lost response remains recoverable using the original key. An empty proposal is not a completed first draft. Unconfigured demand returns generation.demand_unavailable; this operation does not substitute minimum-floor staffing. Signed-in operators and outside clients share the workspace compute limit, while retaining distinct human and token Actors.
MCP example
MCP requiresmcp:connect and native domain grants independently of REST. Send JSON to /api/mcp:
atlas_issue_draft_schedule, atlas_inspect_draft_schedule, and atlas_commit_draft_schedule. Their request_key equals the REST Idempotency-Key. Tools must be visible under real current grants; registration alone is insufficient.
Limits, failures and verification
Requests are bounded to 64 KiB, 14 inclusive dates and 200 roster entries for generation. Heavy calls share one active operation per workspace and token, a 30-second cooperative budget, 10-second database requests and a 45-second deadline across database pages. Admission leases expire after 120 seconds if their completion acknowledgement is lost. They are operational telemetry, not effect receipts; read-only calculations do not write schedule or requirement records. REST errors use{ "error": { "code": "generation.source_changed", "message": "generation source changed" } }. Newly exposed MCP operations return the same actionable structured code. Cases include expired/invalid bearer (401), missing REST or current native grant (403), source/revision conflict (409), invalid input (422), compute concurrency (429), and unavailable evidence (503). A timeout at commit is an unknown outcome: inspect and reuse the same native draft key.
Run scripts/workforce/smoke-external.mjs against an authorized deployment to exercise real HTTP REST and MCP without cookies or service-role credentials. Full source-to-draft and live customer activation require separately retained acceptance evidence. Confirmed command success does not establish later service improvement.
Review, preflight and verification
GET /api/v1/workforce/setup/assessment and atlas_read_workforce_assessment
read an owned assessment, its retained revisions and currently authorized conversation.
sessionId is required; resultRef selects an earlier revision. after is an optional
history cursor. The original {start,end,timezone} remains unchanged during corrections.
The current source permission checks also apply to older derived analysis. External
provider, prediction and semantic evidence additionally requires the connection’s
corresponding domain grant; workforce read never inherits those grants from its owner.
assessmentAvailability explicitly distinguishes available, pending, wrong-workspace
and unavailable evidence, with an actionable reason for unavailable saved analysis.
History reads admit at most 200 distinct source checks with a 20-second cooperative
budget; a capped read returns workforce.budget_exceeded, never an empty success. No caller
user ID, browser session or substituted workspace identity is accepted.
Review details include cited queue/Person tables, assumptions, reused inputs, decisions,
and separate staffing/evidence issues. They are analysis, not an eligibility grant.
Native preview computes createReady; operationalReadiness: "not_verified" remains
separate. An unavailable historical count is not an observed zero.
POST /api/v1/workforce/setup/check and atlas_check_workforce_setup accept the same
saved selector plus keys and mode. preflight rechecks current authority, source
fingerprints and selected native inputs; it requires a current completed assessment
and the effect’s write/publication grants. verify is read-only and does not provision
an Actor. It compares the original request with the current saved group/publication
or membership. Native commit repeats source, revision, assignment-span, overlap and
FTE validation; preflight does not reserve capacity or promise a later commit.
verified; separate successful effects remain committed after a later failure.
If a response is lost, verify the original selector before retrying the same command.
not_confirmed means no effect was found for that issuer/key; unknown means the
read could not establish an outcome; changed means the saved current record differs
from the review. Neither is an applied-and-verified success. Human and token Actors
retain their existing distinct command ownership; REST/MCP replay uses the same token.
A superseded preflight returns 409 workforce.assessment_superseded; invalid or duplicate
selection keys return 422; revoked domain authority returns 403; admission contention
returns 429 workforce.compute_busy. A per-item blocked source check explains why
no apply should start. Structured MCP failures retain the same actionable code.
A verified configuration is not a demand-backed draft, provider activation or evidence
of improved service. Those subsequent operations retain their own native checks.
Setup progress and run deletion
Useview=summary with the existing assessment read operation to poll progress.
It returns four plain-language sections and the run’s state. While a run is active,
it does not hydrate the conversation or repeat source queries. Once complete, it
loads the selected plan with the same current source permission checks. checked
means a request returned; the plan establishes which evidence is usable. Full
source-authorized history remains available with view=history (the default).
The assessment list includes needsAttention metadata. A run can complete with
blockers or an inspection-limit failure; these display as “Needs attention”.
Completion and this summary flag do not establish scheduling readiness. Open the
result for its currently authorized findings.
manage_schedules
authority. It closes only that Person’s setup run and records the acting Actor.
It preserves saved groups, schedules and native command receipts. A running
lease or temporary storage outage returns {deleted:false,cleanupPending:true};
the run is hidden immediately and existing native cleanup retries its removal.
Absent and foreign runs both return {deleted:true,cleanupPending:false}.
Missing write grants return 403; extra identity fields are invalid input.
The setup agent uses the same native kernel with a focused read/plan tool set.
It stops source discovery after twelve steps and finishes by sixteen, retaining
a native plan or an explicit implementation blocker. Invalid read arguments do
not erase subsequent corrections. Fixed tool diagnostics distinguish malformed
input (invalid_tool_input), an operation outside the agent’s configuration
(operation_not_configured) and unusable evidence (citation_unavailable).
They contain no source contents and do not authorize access to cited results.
These bounds do not turn an unavailable
source, blocked plan or empty proposal into a completed first draft.