Update Action State

Use UpdateActionState to advance an Action through its lifecycle or report execution progress. This operation changes state, progress, and optional provenance; it does not rewrite the original Action content.

package main

import (
	"context"
	"log"
	"time"

	"connectrpc.com/connect"
	"google.golang.org/protobuf/types/known/timestamppb"

	wdmsdk "github.com/raft-tech/raft-wdm-sdk-go"
	pb "github.com/raft-tech/raft-wdm-sdk-go/gen/raft/wdm/v1"
	svc "github.com/raft-tech/raft-wdm-sdk-go/gen/raft/wdm/v1/service"
)

func main() {
	cfg, err := wdmsdk.LoadConfig()
	if err != nil {
		log.Fatal(err)
	}

	client, err := wdmsdk.NewFromConfig(cfg)
	if err != nil {
		log.Fatal(err)
	}

	_, err = client.ActionService().UpdateActionState(context.Background(), connect.NewRequest(&svc.UpdateActionStateRequest{
		ActionId: "isr-collect-alpha",
		State:    pb.ActionState_ACTION_STATE_IN_PROGRESS,
		Progress: &pb.ActionProgress{
			Phase:         "ON_STATION",
			StatusMessage: "Asset on station, commencing collection orbit",
		},
		Provenance: &pb.ProvenanceRecord{
			Name:      "uav-shadow-07",
			UpdatedAt: timestamppb.New(time.Now().UTC()),
		},
	}))
	if err != nil {
		log.Fatal(err)
	}
}
import com.google.protobuf.Timestamp;
import com.raft.wdm.Wdm;
import com.raft.wdm.raft.wdm.v1.ActionProgress;
import com.raft.wdm.raft.wdm.v1.ActionState;
import com.raft.wdm.raft.wdm.v1.ProvenanceRecord;
import com.raft.wdm.raft.wdm.v1.service.UpdateActionStateRequest;
import com.raft.wdm.v1.WdmV1Client;
import java.time.Instant;

public final class UpdateActionStateExample {
  public static void main(String[] args) {
    var options = Wdm.toOptions(Wdm.loadConfig(null, null));

    try (var client = WdmV1Client.create(options)) {
      var req = UpdateActionStateRequest.newBuilder()
          .setActionId("isr-collect-alpha")
          .setState(ActionState.ACTION_STATE_IN_PROGRESS)
          .setProgress(ActionProgress.newBuilder()
              .setPhase("ON_STATION")
              .setStatusMessage("Asset on station, commencing collection orbit"))
          .setProvenance(ProvenanceRecord.newBuilder()
              .setName("uav-shadow-07")
              .setUpdatedAt(timestamp(Instant.now())))
          .build();

      client.getActionService()
          .updateActionStateBlocking(req)
          .execute();
    }
  }

  private static Timestamp timestamp(Instant instant) {
    return Timestamp.newBuilder()
        .setSeconds(instant.getEpochSecond())
        .setNanos(instant.getNano())
        .build();
  }
}
import asyncio
from datetime import datetime, timezone

from google.protobuf.timestamp_pb2 import Timestamp
from raft.wdm.v1 import action_pb2
from raft.wdm.v1 import common_pb2
from raft.wdm.v1.service import action_service_pb2

import raft_wdm_sdk


def timestamp(dt: datetime) -> Timestamp:
    value = Timestamp()
    value.FromDatetime(dt)
    return value


async def main() -> None:
    async with raft_wdm_sdk.Client.from_config(raft_wdm_sdk.load_config()) as client:
        await client.action_service.update_action_state(
            action_service_pb2.UpdateActionStateRequest(
                action_id="isr-collect-alpha",
                state=action_pb2.ACTION_STATE_IN_PROGRESS,
                progress=action_pb2.ActionProgress(
                    phase="ON_STATION",
                    status_message="Asset on station, commencing collection orbit",
                ),
                provenance=common_pb2.ProvenanceRecord(
                    name="uav-shadow-07",
                    updated_at=timestamp(datetime.now(timezone.utc)),
                ),
            ),
        )


asyncio.run(main())
import { create } from "@bufbuild/protobuf";
import { timestampFromDate } from "@bufbuild/protobuf/wkt";
import { createClient, fromNodeConfig, loadConfig } from "@raft-tech/raft-wdm-sdk-typescript";
import { ActionState } from "@raft-tech/raft-wdm-sdk-typescript/gen/raft/wdm/v1/action_pb.js";
import { UpdateActionStateRequestSchema } from "@raft-tech/raft-wdm-sdk-typescript/gen/raft/wdm/v1/service/action_service_pb.js";

const client = createClient(...fromNodeConfig(loadConfig()));

await client.actionService.updateActionState(
  create(UpdateActionStateRequestSchema, {
    actionId: "isr-collect-alpha",
    state: ActionState.IN_PROGRESS,
    progress: {
      phase: "ON_STATION",
      statusMessage: "Asset on station, commencing collection orbit",
    },
    provenance: {
      name: "uav-shadow-07",
      updatedAt: timestampFromDate(new Date()),
    },
  }),
);
curl -X PUT "${RDP_SERVER_URL}/api/v1/wdm/actions/isr-collect-alpha/state" \
  -H "X-API-KEY: ${RDP_API_KEY}" \
  -H "Content-Type: application/json" \
  --json @- <<JSON
{
  "state": "ACTION_STATE_IN_PROGRESS",
  "progress": {
    "phase": "ON_STATION",
    "statusMessage": "Asset on station, commencing collection orbit"
  },
  "provenance": {
    "name": "uav-shadow-07",
    "updatedAt": "2026-05-27T21:31:04Z"
  }
}
JSON

Lifecycle

Move Actions forward through their lifecycle as execution changes. Terminal states are final.

DRAFT -> PENDING -> APPROVED -> ASSIGNED -> ACKNOWLEDGED
  -> PLANNED -> IN_PROGRESS -> COMPLETED

Use ACTION_STATE_CANCELLED to cancel an Action. Use ACTION_STATE_FAILED or ACTION_STATE_REJECTED when execution cannot complete or the assignee rejects the Action.

Progress

Same-state updates are valid. For example, an Action can remain ACTION_STATE_IN_PROGRESS while progress.phase changes from ON_STATION to COLLECTING to RTB.

{
  "actionId": "isr-collect-alpha",
  "state": "ACTION_STATE_IN_PROGRESS",
  "progress": {
    "phase": "COLLECTING",
    "statusMessage": "Collecting imagery on NAI 3"
  },
  "provenance": {
    "name": "uav-shadow-07",
    "updatedAt": "2026-05-27T21:31:04Z"
  }
}

The full contract is defined in the WDM protobuf spec. In the WDM distribution, see raft/wdm/v1/service/action_service.proto for UpdateActionStateRequest and raft/wdm/v1/action.proto for ActionProgress.