Skip to main content

[!FROZEN] MPLP Protocol v1.0.0 Frozen Specification Freeze Date: 2025-12-03 Status: FROZEN (no breaking changes permitted) Governance: MPLP Protocol Governance Committee (MPGC) License: Apache-2.0 Note: Any normative change requires a new protocol version.

Plan Module

1. Purpose

The Plan Module is the engine of agency. It provides the standard structure for decomposing a high-level objective into executable steps. A Plan is a Directed Acyclic Graph (DAG) where steps can depend on the completion of others.

Design Principle: "Structured intent Verifiable execution path"

2. Canonical Schema

From: schemas/v2/mplp-plan.schema.json

2.1 Required Fields

FieldTypeDescription
metaObjectProtocol metadata (version, source)
plan_idUUID v4Global unique identifier
context_idUUID v4Link to parent Context
titleString (min 1 char)Brief plan name
objectiveString (min 1 char)Detailed goal description
statusEnumPlan lifecycle state
stepsArray (min 1)List of PlanStep objects

2.2 Optional Fields

FieldTypeDescription
traceObjectExecution trace reference
eventsArrayLifecycle events (approvals, status changes)

2.3 The PlanStep Object

Required: step_id, description, status

FieldTypeDescription
step_idUUID v4Unique step identifier
descriptionString (min 1 char)Work content
statusEnumStep execution state
dependenciesArray[UUID]Step IDs this step depends on
agent_roleStringRole responsible (role_id)
order_indexInteger 0Display/execution order

3. Lifecycle State Machine

3.1 Plan Status

From schema: ["draft", "proposed", "approved", "in_progress", "completed", "cancelled", "failed"]

3.2 Step Status

From schema: ["pending", "in_progress", "completed", "blocked", "skipped", "failed"]

3.3 Valid Transitions

Plan Status:

FromToTrigger
draftproposedAgent submits
draftcancelledUser abandons
proposedapprovedConfirm.approved=true
proposeddraftConfirm.approved=false
approvedin_progressRuntime starts
in_progresscompletedAll steps completed
in_progressfailedCritical step failed
in_progresscancelledUser requests

Step Status:

FromToTrigger
pendingin_progressAll dependencies completed
pendingblockedAny dependency failed
pendingskippedConditional logic
in_progresscompletedExecution success
in_progressfailedExecution error
blockedpendingDependency retry success

4. DAG Dependency Model

4.1 Dependency Rules

  1. Acyclic: No circular dependencies allowed
  2. Referential: Dependencies MUST reference valid step_id within same Plan
  3. Execution Order: Step executes only when ALL dependencies are completed

4.2 DAG Validation

function validatePlanDAG(plan: Plan): ValidationResult {
const stepIds = new Set(plan.steps.map(s => s.step_id));
const errors: string[] = [];

// Check referential integrity
for (const step of plan.steps) {
for (const dep of step.dependencies || []) {
if (!stepIds.has(dep)) {
errors.push(`Step ${step.step_id} depends on non-existent ${dep}`);
}
}
}

// Check for cycles (DFS)
const visited = new Set<string>();
const recursionStack = new Set<string>();

function hasCycle(stepId: string): boolean {
if (recursionStack.has(stepId)) return true;
if (visited.has(stepId)) return false;

visited.add(stepId);
recursionStack.add(stepId);

const step = plan.steps.find(s => s.step_id === stepId);
for (const dep of step?.dependencies || []) {
if (hasCycle(dep)) return true;
}

recursionStack.delete(stepId);
return false;
}

for (const step of plan.steps) {
if (hasCycle(step.step_id)) {
errors.push('Cyclic dependency detected');
break;
}
}

return { valid: errors.length === 0, errors };
}

4.3 Example DAG

   s1 (Analyze Requirements)  s2 (Design Architecture) s4 (Implement Core)   s3 (Setup Testing) s5 (Integration Test)
{
"steps": [
{ "step_id": "s1", "description": "Analyze Requirements", "dependencies": [] },
{ "step_id": "s2", "description": "Design Architecture", "dependencies": ["s1"] },
{ "step_id": "s3", "description": "Setup Testing", "dependencies": ["s1"] },
{ "step_id": "s4", "description": "Implement Core", "dependencies": ["s2"] },
{ "step_id": "s5", "description": "Integration Test", "dependencies": ["s3", "s4"] }
]
}

5. Normative Requirements

From: schemas/v2/invariants/sa-invariants.yaml

5.1 Core Invariants

IDRuleDescription
sa_plan_min_stepssteps.length >= 1Plan MUST have at least one step
sa_plan_context_bindingplan.context_id == context.context_idPlan bound to loaded Context
sa_plan_step_unique_idsAll step_id uniqueNo duplicate step IDs
sa_plan_dag_acyclicNo cyclesDependencies form valid DAG

5.2 Execution Invariants

  • Plan can only transition to in_progress when Context status == 'active'
  • Step can only be in_progress when Plan status == 'in_progress'
  • Plan is completed when ALL steps are completed or skipped
  • Plan is failed when ANY critical step is failed

6. Module Interactions

6.1 Dependency Map

Plan Module  Context Module        Plan.context_id MUST reference valid Context  Confirm Module        proposed approved requires Confirm.approved=true  Trace Module        Each step execution emits Trace Span  Role Module
step.agent_role references role_id

7. SDK Examples

7.1 TypeScript (Creating Plan)

import { v4 as uuidv4 } from 'uuid';

type PlanStatus = 'draft' | 'proposed' | 'approved' | 'in_progress' | 'completed' | 'cancelled' | 'failed';
type StepStatus = 'pending' | 'in_progress' | 'completed' | 'blocked' | 'skipped' | 'failed';

interface PlanStep {
step_id: string;
description: string;
status: StepStatus;
dependencies?: string[];
agent_role?: string;
order_index?: number;
}

interface Plan {
meta: { protocolVersion: string };
plan_id: string;
context_id: string;
title: string;
objective: string;
status: PlanStatus;
steps: PlanStep[];
}

function createPlan(
context_id: string,
title: string,
objective: string,
steps: Omit<PlanStep, 'status'>[]
): Plan {
return {
meta: { protocolVersion: '1.0.0' },
plan_id: uuidv4(),
context_id,
title,
objective,
status: 'draft',
steps: steps.map((s, i) => ({
...s,
status: 'pending' as StepStatus,
order_index: i
}))
};
}

// Usage
const plan = createPlan(
'ctx-123',
'Fix Login Bug',
'Investigate and fix 500 error on /login',
[
{ step_id: 's1', description: 'Read error logs', dependencies: [] },
{ step_id: 's2', description: 'Identify root cause', dependencies: ['s1'] },
{ step_id: 's3', description: 'Write fix', dependencies: ['s2'], agent_role: 'coder' }
]
);

7.2 Python (Pydantic Model)

from pydantic import BaseModel, Field
from uuid import uuid4
from typing import List, Optional
from enum import Enum

class PlanStatus(str, Enum):
DRAFT = 'draft'
PROPOSED = 'proposed'
APPROVED = 'approved'
IN_PROGRESS = 'in_progress'
COMPLETED = 'completed'
CANCELLED = 'cancelled'
FAILED = 'failed'

class StepStatus(str, Enum):
PENDING = 'pending'
IN_PROGRESS = 'in_progress'
COMPLETED = 'completed'
BLOCKED = 'blocked'
SKIPPED = 'skipped'
FAILED = 'failed'

class PlanStep(BaseModel):
step_id: str = Field(default_factory=lambda: str(uuid4()))
description: str = Field(..., min_length=1)
status: StepStatus = StepStatus.PENDING
dependencies: List[str] = []
agent_role: Optional[str] = None
order_index: Optional[int] = None

class Plan(BaseModel):
plan_id: str = Field(default_factory=lambda: str(uuid4()))
context_id: str
title: str = Field(..., min_length=1)
objective: str = Field(..., min_length=1)
status: PlanStatus = PlanStatus.DRAFT
steps: List[PlanStep] = Field(..., min_items=1)

# Usage
plan = Plan(
context_id='ctx-123',
title='Fix Login Bug',
objective='Investigate and fix 500 error on /login',
steps=[
PlanStep(step_id='s1', description='Read error logs'),
PlanStep(step_id='s2', description='Identify root cause', dependencies=['s1'])
]
)

8. Complete JSON Example

{
"meta": {
"protocolVersion": "1.0.0",
"source": "mplp-sdk-ts"
},
"plan_id": "plan-550e8400-e29b-41d4-a716-446655440001",
"context_id": "ctx-550e8400-e29b-41d4-a716-446655440000",
"title": "Fix Login Bug",
"objective": "Investigate and fix the 500 error on /login endpoint in production",
"status": "in_progress",
"steps": [
{
"step_id": "s1",
"description": "Read server error logs from past 24 hours",
"status": "completed",
"dependencies": [],
"agent_role": "debugger",
"order_index": 0
},
{
"step_id": "s2",
"description": "Identify root cause from stack traces",
"status": "completed",
"dependencies": ["s1"],
"agent_role": "debugger",
"order_index": 1
},
{
"step_id": "s3",
"description": "Write code patch for null pointer exception",
"status": "in_progress",
"dependencies": ["s2"],
"agent_role": "coder",
"order_index": 2
},
{
"step_id": "s4",
"description": "Write unit tests for the fix",
"status": "pending",
"dependencies": ["s3"],
"agent_role": "coder",
"order_index": 3
},
{
"step_id": "s5",
"description": "Deploy to staging and verify",
"status": "pending",
"dependencies": ["s3", "s4"],
"agent_role": "devops",
"order_index": 4
}
],
"trace": {
"trace_id": "trace-plan-550e8401"
}
}

Schemas:

  • schemas/v2/mplp-plan.schema.json
  • schemas/v2/invariants/sa-invariants.yaml

Architecture:

Modules:


Document Status: Normative (Core Module)
Required Fields: meta, plan_id, context_id, title, objective, status, steps
Plan Status: draft proposed approved in_progress completed/failed/cancelled
Step Status: pending in_progress completed/failed/blocked/skipped
Key Invariant: steps.length 1, DAG must be acyclic

2025 Bangshi Beijing Network Technology Limited Company Licensed under the Apache License, Version 2.0.