Work Order System — Agent Message Contracts
Classification: Internal — Agent Architecture Date: 2026-02-13 Status: Proposed Pattern: LangGraph-style typed message routing with CODITECT orchestrator-workers
1. Agent Graph Topology
1.1 Node Registry
| Node | Input Messages | Output Messages | State Access |
|---|---|---|---|
WorkOrderOrchestrator | WorkOrderIntent, TransitionCommand, SubAgentResult | SubWorkOrderIntent, StateChange, GuardViolation | Read/Write WO, Dependencies |
AssetManagement | AssetChangeRequest | AssetChangeResult, AssetValidationFailure | Read/Write Assets |
Scheduling | SchedulingRequest | ScheduleProposal, SchedulingFailure | Read Schedule, TimeEntry, Person |
ExperienceMatching | StaffingRequest | StaffingProposal, StaffingGap | Read PersonExperience |
QAReview | QAReviewRequest, QAReviewDecision | QAReviewPending, QAPreCheckFailed, QADecided | Read/Write Approval, Signature |
VendorCoordinator | VendorTaskRequest | VendorTaskUpdate, VendorArtifactAttached | Read/Write Vendor WOs |
Documentation | DocUpdateRequest | DocUpdateResult, DocMissing | Read/Write ChangeItem.documentId |
1.2 Edge Map
┌──────────────────────────────────────────┐
│ WorkOrderOrchestrator │
│ │
│ Routes messages by type: │
│ AssetChangeRequest → AssetManagement │
│ SchedulingRequest → Scheduling │
│ StaffingRequest → ExperienceMatching │
│ QAReviewRequest → QAReview │
│ VendorTaskRequest → VendorCoordinator │
│ DocUpdateRequest → Documentation │
└───┬──┬──┬──┬──┬──┬───────────────────────┘
│ │ │ │ │ │
┌───────────────┘ │ │ │ │ └──────────────┐
│ ┌───────────────┘ │ │ └──────────┐ │
│ │ ┌───────────────┘ └──────┐ │ │
▼ ▼ ▼ ▼ ▼ ▼
┌──────┐┌────────┐┌───────────┐┌────────┐┌──────┐┌─────┐
│Asset ││Schedule││Experience ││QA ││Vendor││Docs │
│Mgmt ││ ││Matching ││Review ││Coord ││ │
└──┬───┘└───┬────┘└─────┬─────┘└───┬────┘└──┬───┘└──┬──┘
│ │ │ │ │ │
└────────┴───────────┴───────────┴────────┴───────┘
│
All results return to
WorkOrderOrchestrator
2. Message Type System
2.1 Base Message Interface
interface AgentMessage {
id: string; // Unique message ID (cuid)
type: string; // Discriminator for routing
correlationId: string; // Distributed trace ID
tenantId: string; // Tenant isolation
timestamp: string; // ISO 8601
source: {
nodeId: string; // Sending agent node
sessionId: string; // Agent execution session
};
metadata: {
priority: number; // 1-5
ttlMs: number; // Message time-to-live
retryCount: number; // Current retry attempt
maxRetries: number; // Max retry attempts
tokenBudget?: number; // Remaining token budget
};
}
2.2 Orchestrator Messages
// Inbound: External intent to create or manage a work order
interface WorkOrderIntent extends AgentMessage {
type: 'WorkOrderIntent';
payload: {
intentType: 'CREATE_MASTER' | 'CREATE_LINKED' | 'UPGRADE' | 'CALIBRATION' | 'DECOMMISSION';
description: string;
itemId: string;
regulatoryFlag: boolean;
complianceClass?: string;
templateId?: string; // JobPlan template to clone
requestedBy: string; // Person or Party ID
};
}
// Inbound: Explicit state transition command
interface TransitionCommand extends AgentMessage {
type: 'TransitionCommand';
payload: {
workOrderId: string;
targetStatus: WorkOrderStatus;
performedBy: string;
signatureId?: string; // Required for APPROVED/REJECTED
comment?: string;
};
}
// Outbound: Orchestrator creates sub-WO intents for child WOs
interface SubWorkOrderIntent extends AgentMessage {
type: 'SubWorkOrderIntent';
payload: {
masterWorkOrderId: string;
childDescription: string;
childSourceType: 'AUTOMATION' | 'EXTERNAL_VENDOR' | 'MANUAL';
sequenceOrder: number;
dependsOn: string[]; // WO IDs that must complete first
assignToAgent: string; // Target agent node
jobPlanTemplateId?: string;
};
}
// Outbound: State change notification
interface WorkOrderStateChange extends AgentMessage {
type: 'WorkOrderStateChange';
payload: {
workOrderId: string;
previousStatus: WorkOrderStatus;
newStatus: WorkOrderStatus;
triggeredBy: string;
auditTrailId: string;
};
}
// Outbound: Guard violation (transition blocked)
interface GuardViolation extends AgentMessage {
type: 'GuardViolation';
payload: {
workOrderId: string;
attemptedTransition: { from: WorkOrderStatus; to: WorkOrderStatus };
violations: string[];
suggestedAction: string;
};
}
2.3 Asset Management Messages
interface AssetChangeRequest extends AgentMessage {
type: 'AssetChangeRequest';
payload: {
workOrderId: string;
assetId: string;
action: 'REMOVE_FROM_PRODUCTION' | 'DECOMMISSION' | 'REVALIDATE' | 'UPDATE_STATUS';
targetStatus: string;
externalTicketRef?: string; // CMMS/ITSM ticket ID
};
}
interface AssetChangeResult extends AgentMessage {
type: 'AssetChangeResult';
payload: {
workOrderId: string;
assetId: string;
previousStatus: string;
newStatus: string;
externalTicketRef?: string;
success: boolean;
error?: string;
};
}
interface AssetValidationFailure extends AgentMessage {
type: 'AssetValidationFailure';
payload: {
workOrderId: string;
assetId: string;
reason: string; // "Asset not found", "Asset already decommissioned", etc.
suggestedAction: string;
};
}
2.4 Scheduling Messages
interface SchedulingRequest extends AgentMessage {
type: 'SchedulingRequest';
payload: {
workOrderId: string;
jobPlanId: string;
preferredWindow: {
earliest: string; // ISO 8601
latest: string;
};
constraints: {
requiredPersonIds?: string[];
requiredToolIds?: string[];
excludeDates?: string[];
maxDurationHours?: number;
};
};
}
interface ScheduleProposal extends AgentMessage {
type: 'ScheduleProposal';
payload: {
workOrderId: string;
proposedSchedule: {
startAt: string;
endAt: string;
totalHours: number;
};
assignedPersons: Array<{
personId: string;
role: string;
hours: number;
}>;
assignedTools: Array<{
toolId: string;
fromDate: string;
toDate: string;
}>;
confidence: number; // 0.0–1.0
alternatives?: Array<{ // Up to 3 alternatives if confidence < 0.8
startAt: string;
endAt: string;
tradeoff: string;
}>;
};
}
interface SchedulingFailure extends AgentMessage {
type: 'SchedulingFailure';
payload: {
workOrderId: string;
reason: 'NO_AVAILABLE_PERSONS' | 'NO_AVAILABLE_TOOLS' | 'WINDOW_TOO_NARROW' | 'CONFLICT';
details: string;
suggestedAction: string;
};
}
2.5 Experience Matching Messages
interface StaffingRequest extends AgentMessage {
type: 'StaffingRequest';
payload: {
workOrderId: string;
requirements: Array<{
experienceId: string;
experienceName: string;
minRating: number;
mandatory: boolean;
}>;
headcount: number;
preferredPersonIds?: string[];
excludePersonIds?: string[];
};
}
interface StaffingProposal extends AgentMessage {
type: 'StaffingProposal';
payload: {
workOrderId: string;
candidates: Array<{
personId: string;
personName: string;
fitScore: number; // 0.0–1.0
experienceMatch: Array<{
experienceId: string;
requiredRating: number;
actualRating: number;
certified: boolean;
certExpires?: string;
}>;
availability: 'AVAILABLE' | 'PARTIAL' | 'UNAVAILABLE';
}>;
gapsIdentified: Array<{
experienceId: string;
experienceName: string;
bestAvailableRating: number;
requiredRating: number;
}>;
};
}
interface StaffingGap extends AgentMessage {
type: 'StaffingGap';
payload: {
workOrderId: string;
unmetRequirements: Array<{
experienceId: string;
experienceName: string;
requiredRating: number;
bestAvailable: number;
}>;
suggestedActions: string[]; // "Train person X", "Hire contractor", etc.
};
}
2.6 QA Review Messages
interface QAReviewRequest extends AgentMessage {
type: 'QAReviewRequest';
payload: {
workOrderId: string;
regulatoryFlag: boolean;
complianceClass?: string;
requiredArtifacts: string[]; // ["IQ_REPORT", "OQ_REPORT", "GOLDEN_IMAGE", "WI_UPDATE"]
childWOStatuses: Array<{
childId: string;
status: WorkOrderStatus;
}>;
};
}
interface QAReviewPending extends AgentMessage {
type: 'QAReviewPending';
payload: {
workOrderId: string;
assignedQAUserId: string;
expectedCompletionAt: string;
};
}
interface QAPreCheckFailed extends AgentMessage {
type: 'QAPreCheckFailed';
payload: {
workOrderId: string;
missingArtifacts: string[];
incompleteChildWOs: string[];
reason: string;
};
}
interface QAReviewDecision extends AgentMessage {
type: 'QAReviewDecision';
payload: {
workOrderId: string;
qaUserId: string;
decision: 'APPROVED' | 'REJECTED';
comment?: string;
signatureId: string; // e-Signature ID (required)
findings: Array<{
severity: 'CRITICAL' | 'MAJOR' | 'MINOR' | 'OBSERVATION';
description: string;
remediation?: string;
}>;
};
}
2.7 Vendor Coordination Messages
interface VendorTaskRequest extends AgentMessage {
type: 'VendorTaskRequest';
payload: {
workOrderId: string;
vendorId: string;
taskType: 'INSTALL' | 'IQ_OQ' | 'CALIBRATION' | 'REPAIR' | 'UPGRADE';
description: string;
requiredDeliverables: string[]; // ["IQ_REPORT", "OQ_REPORT", "CERTIFICATE"]
deadline: string;
};
}
interface VendorTaskUpdate extends AgentMessage {
type: 'VendorTaskUpdate';
payload: {
workOrderId: string;
vendorId: string;
status: 'ACKNOWLEDGED' | 'IN_PROGRESS' | 'COMPLETED' | 'DELAYED';
progressPercent: number;
notes?: string;
estimatedCompletion?: string;
};
}
interface VendorArtifactAttached extends AgentMessage {
type: 'VendorArtifactAttached';
payload: {
workOrderId: string;
vendorId: string;
artifactType: string; // "IQ_REPORT", "OQ_REPORT", "CERTIFICATE"
documentRef: string; // DMS document ID
attachedAt: string;
};
}
2.8 Documentation Messages
interface DocUpdateRequest extends AgentMessage {
type: 'DocUpdateRequest';
payload: {
workOrderId: string;
updateType: 'CREATE_WI' | 'UPDATE_WI' | 'CAPTURE_GOLDEN_IMAGE' | 'LINK_DOCUMENT';
documentType: string;
description: string;
relatedAssetId?: string;
};
}
interface DocUpdateResult extends AgentMessage {
type: 'DocUpdateResult';
payload: {
workOrderId: string;
documentRef: string;
documentVersion: number;
status: 'CREATED' | 'UPDATED' | 'LINKED';
};
}
interface DocMissing extends AgentMessage {
type: 'DocMissing';
payload: {
workOrderId: string;
missingDocuments: Array<{
type: string;
description: string;
required: boolean;
}>;
suggestedAction: string;
};
}
3. Message Routing Rules
3.1 Orchestrator Router Implementation
class OrchestratorRouter {
private routes: Map<string, string> = new Map([
['AssetChangeRequest', 'asset_mgmt'],
['SchedulingRequest', 'scheduling'],
['StaffingRequest', 'experience_matching'],
['QAReviewRequest', 'qa_review'],
['VendorTaskRequest', 'vendor_coord'],
['DocUpdateRequest', 'documentation'],
]);
private resultHandlers: Map<string, (msg: AgentMessage) => Promise<void>> = new Map([
['AssetChangeResult', this.handleAssetResult.bind(this)],
['ScheduleProposal', this.handleScheduleProposal.bind(this)],
['StaffingProposal', this.handleStaffingProposal.bind(this)],
['QAReviewDecision', this.handleQADecision.bind(this)],
['VendorTaskUpdate', this.handleVendorUpdate.bind(this)],
['VendorArtifactAttached', this.handleVendorArtifact.bind(this)],
['DocUpdateResult', this.handleDocResult.bind(this)],
]);
async route(msg: AgentMessage): Promise<void> {
// Check token budget
if (msg.metadata.tokenBudget !== undefined && msg.metadata.tokenBudget <= 0) {
throw new BudgetExhaustedError(msg);
}
// Route outbound requests
const targetNode = this.routes.get(msg.type);
if (targetNode) {
await this.dispatch(targetNode, msg);
return;
}
// Handle inbound results
const handler = this.resultHandlers.get(msg.type);
if (handler) {
await handler(msg);
return;
}
throw new UnknownMessageTypeError(msg.type);
}
}
3.2 Error Routing
| Error Condition | Message Emitted | Recovery |
|---|---|---|
| Agent node timeout | AgentTimeout | Retry up to maxRetries, then escalate |
| Guard violation | GuardViolation | Return to caller with violation details |
| Budget exhausted | BudgetExhausted | Checkpoint state, halt execution |
| Dependency cycle | DependencyCycleDetected | Block WO creation, return error |
| Signature invalid | SignatureValidationFailed | Reject approval, require re-sign |
4. Win10 → Win11 Upgrade: Complete Message Flow
4.1 Message Sequence (13 Steps)
Step From To Message Type Key Payload
──────────────────────────────────────────────────────────────────────────────────────────────────────
1 Client Orchestrator WorkOrderIntent {intentType: 'UPGRADE', regulatory: true}
2 Orchestrator Orchestrator SubWorkOrderIntent ×6 6 child WOs created with dependencies
3 Orchestrator AssetMgmt AssetChangeRequest {action: 'REMOVE_FROM_PRODUCTION'}
4 AssetMgmt Orchestrator AssetChangeResult {success: true, newStatus: 'OUT_OF_PRODUCTION'}
5 Orchestrator Scheduling SchedulingRequest {jobPlanId: 'IT_BUILD_WIN11'}
6 Scheduling ExperienceMatching StaffingRequest {requirements: [{name: 'Win11 build', min: 3}]}
7 ExperienceMatching Scheduling StaffingProposal {candidates: [{fitScore: 0.92}]}
8 Scheduling Orchestrator ScheduleProposal {startAt: '...', assignedPersons: [...]}
9 Orchestrator VendorCoord VendorTaskRequest {taskType: 'IQ_OQ', vendorId: '...'}
10 VendorCoord Orchestrator VendorArtifactAttached {artifactType: 'IQ_REPORT'}
11 Orchestrator Documentation DocUpdateRequest {updateType: 'CAPTURE_GOLDEN_IMAGE'}
12 Documentation Orchestrator DocUpdateResult {status: 'CREATED'}
13 Orchestrator QAReview QAReviewRequest {requiredArtifacts: ['IQ_REPORT', 'GOLDEN_IMAGE']}
QAReview Orchestrator QAReviewDecision {decision: 'APPROVED', signatureId: '...'}
Orchestrator (Event Bus) WorkOrderStateChange {newStatus: 'APPROVED'}
Orchestrator (Event Bus) WorkOrderStateChange {newStatus: 'COMPLETED'}
4.2 Token Budget Consumption
| Step | Agent | Estimated Tokens | Cumulative |
|---|---|---|---|
| 1 | Orchestrator (classify + plan) | 2,000 | 2,000 |
| 2 | Orchestrator (create 6 child WOs) | 3,000 | 5,000 |
| 3-4 | AssetMgmt | 1,500 | 6,500 |
| 5-8 | Scheduling + ExperienceMatching | 4,000 | 10,500 |
| 9-10 | VendorCoordinator | 2,000 | 12,500 |
| 11-12 | Documentation | 1,500 | 14,000 |
| 13 | QAReview | 3,000 | 17,000 |
| Total | ~17,000 tokens |
Budget allocation: 50,000 (complex) → 17,000 consumed → 33,000 remaining for error recovery and iteration.
5. NATS Topic Mapping
const topics = {
// Command topics (point-to-point)
'wo.orchestrator.intent': 'WorkOrderIntent',
'wo.orchestrator.transition': 'TransitionCommand',
'wo.asset.change': 'AssetChangeRequest',
'wo.scheduling.request': 'SchedulingRequest',
'wo.staffing.request': 'StaffingRequest',
'wo.qa.review.request': 'QAReviewRequest',
'wo.vendor.task': 'VendorTaskRequest',
'wo.docs.update': 'DocUpdateRequest',
// Result topics (point-to-point back to orchestrator)
'wo.orchestrator.result.asset': 'AssetChangeResult',
'wo.orchestrator.result.schedule': 'ScheduleProposal',
'wo.orchestrator.result.staffing': 'StaffingProposal',
'wo.orchestrator.result.qa': 'QAReviewDecision',
'wo.orchestrator.result.vendor': 'VendorTaskUpdate',
'wo.orchestrator.result.docs': 'DocUpdateResult',
// Event topics (pub/sub, consumed by observability + compliance)
'wo.lifecycle.state_change': 'WorkOrderStateChange',
'wo.compliance.guard_violation': 'GuardViolation',
'wo.compliance.signature': 'SignatureEvent',
'wo.compliance.approval': 'ApprovalEvent',
};