> ## Documentation Index
> Fetch the complete documentation index at: https://docs.getmodus.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Update a workflow

> Updates the workflow’s draft and returns it. Call POST /workflows/{id}/deploy to publish. Use `updateMask` to limit which fields change. Updates that would revoke your own access are rejected.

**Requires:** `workflows:write`



## OpenAPI

````yaml https://api.getmodus.com/openapi.json patch /api/v1/workflows/{id}
openapi: 3.0.3
info:
  title: Modus Public API
  version: 1.0.0
servers: []
security:
  - bearerAuth: []
tags:
  - name: Scopes
    description: Create, configure, deploy, and manage scopes.
  - name: Scopes · Conversations
    description: Read scope conversation threads.
  - name: Scopes · Supervision
    description: Scope supervision sub-resource.
  - name: Scopes · Memories
    description: Long-term memory stored per scope.
  - name: Scopes · Chat
    description: Chat with a published scope.
  - name: Scopes · Context
    description: Compose a scope’s context without an LLM call.
  - name: Modus · Chat
    description: Chat with Modus — your org-wide assistant.
  - name: Modus · Conversations
    description: Read Modus and cross-scope conversation threads.
  - name: Modus · Context
    description: Compose full-environment context without an LLM call.
  - name: Workflows
    description: Create, configure, deploy, and manage workflows.
  - name: Workflows · Runs
    description: Inspect workflow run history.
  - name: Workflows · Interfaces
    description: Slack / MCP / Teams interface management.
  - name: Connections
    description: Read connected integrations.
  - name: Tools
    description: Catalog of tools/integrations a scope can select in its toolset.
  - name: Suggestions
    description: Approved suggested questions and first-party suggestion usage events.
  - name: Context
    description: Create and manage organization context items.
  - name: Usage
    description: Organization LLM usage reporting.
  - name: Users
    description: Organization and membership management.
  - name: Runs · Streaming
    description: 'Run lifecycle: stream, poll, resume, interrupt, and cancel executions.'
  - name: Scopes · Runs
    description: Run a published or draft scope.
  - name: Modus · Runs
    description: Run the Modus home agent.
paths:
  /api/v1/workflows/{id}:
    patch:
      tags:
        - Workflows
      summary: Update a workflow
      description: >-
        Updates the workflow’s draft and returns it. Call POST
        /workflows/{id}/deploy to publish. Use `updateMask` to limit which
        fields change. Updates that would revoke your own access are rejected.


        **Requires:** `workflows:write`
      operationId: WorkflowsController_update
      parameters:
        - name: id
          required: true
          in: path
          description: Numeric workflow id.
          schema:
            example: 42
            type: number
        - name: updateMask
          required: false
          in: query
          description: >-
            Comma-separated list of fields to update. Omit to update all
            provided fields.
          schema:
            example: name,trigger
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateAgentDto'
            examples:
              rename:
                value:
                  name: Daily Sales Report v2
              reschedule:
                value:
                  trigger:
                    trigger_type: schedule
                    schedule:
                      frequency: hourly
                      time_of_day: '00:00'
                      timezone: UTC
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkflowDto'
        '400':
          description: >-
            Malformed request — invalid query parameters or request body (`code:
            BAD_REQUEST`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponseDto'
              example:
                error:
                  code: BAD_REQUEST
                  status: INVALID_ARGUMENT
                  message: Invalid value for query parameter `pageSize`.
                  requestId: req_01HQ7K8ABCDEFGHIJKLMNOPQRS
        '401':
          description: 'Missing, invalid, or expired access token (`code: UNAUTHORIZED`).'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponseDto'
              example:
                error:
                  code: UNAUTHORIZED
                  status: UNAUTHENTICATED
                  message: Missing or invalid access token.
                  requestId: req_01HQ7K8ABCDEFGHIJKLMNOPQRS
        '403':
          description: >-
            Authenticated, but the token lacks a required scope (`code:
            FORBIDDEN`). The missing scopes are listed in `info`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponseDto'
              example:
                error:
                  code: FORBIDDEN
                  status: PERMISSION_DENIED
                  message: Missing required scope(s) for this operation.
                  requestId: req_01HQ7K8ABCDEFGHIJKLMNOPQRS
                  info:
                    missing:
                      - <required-scope>
        '404':
          description: >-
            The resource does not exist, or you do not have access to it (`code:
            NOT_FOUND`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponseDto'
              example:
                error:
                  code: NOT_FOUND
                  status: NOT_FOUND
                  message: Resource not found.
                  requestId: req_01HQ7K8ABCDEFGHIJKLMNOPQRS
        '409':
          description: >-
            The request conflicts with the current state of the resource, e.g. a
            duplicate (`code: CONFLICT`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponseDto'
              example:
                error:
                  code: CONFLICT
                  status: ALREADY_EXISTS
                  message: A resource with that identifier already exists.
                  requestId: req_01HQ7K8ABCDEFGHIJKLMNOPQRS
        '422':
          description: >-
            The request was well-formed but failed a business rule (`code:
            VALIDATION`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponseDto'
              example:
                error:
                  code: VALIDATION
                  status: INVALID_ARGUMENT
                  message: Updates that would revoke your own access are not allowed.
                  requestId: req_01HQ7K8ABCDEFGHIJKLMNOPQRS
        '500':
          description: 'An unexpected server error occurred (`code: INTERNAL_ERROR`).'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponseDto'
              example:
                error:
                  code: INTERNAL_ERROR
                  status: INTERNAL
                  message: An unexpected error occurred.
                  requestId: req_01HQ7K8ABCDEFGHIJKLMNOPQRS
      security:
        - bearerAuth: []
      servers:
        - url: https://api.getmodus.com
components:
  schemas:
    UpdateAgentDto:
      type: object
      properties:
        name:
          type: string
          description: New display name for the workflow.
          example: Daily Sales Report v2
          minLength: 1
          maxLength: 200
        type:
          description: Updated workflow type. Rarely changed after creation.
          example: task
          allOf:
            - $ref: '#/components/schemas/AgentType'
        description:
          type: string
          description: Updated description.
          example: Generates a daily sales report broken down by region.
        trigger:
          description: >-
            Updated trigger configuration. Schedule shape is fully validated;
            other trigger types are opaque.
          allOf:
            - $ref: '#/components/schemas/TriggerDto'
        agentSelection:
          description: Updated workflow selection.
          allOf:
            - $ref: '#/components/schemas/AgentSelectionDto'
        workflowStructure:
          description: >-
            Updated workflow graph (nodes + edges). Unknown node/edge keys and
            out-of-enum node types are rejected with a 422.
          allOf:
            - $ref: '#/components/schemas/WorkflowStructureDto'
        accessConfig:
          description: >-
            Updated access configuration. The service rejects changes that would
            lock the caller out of use + manage.
          allOf:
            - $ref: '#/components/schemas/AgentAccessConfigDto'
    WorkflowDto:
      type: object
      properties:
        id:
          type: number
          description: Numeric workflow id (stable per-org; not reused after delete).
          example: 42
        slug:
          type: string
          description: URL-safe slug used in human-readable links. Unique per org.
          example: customer-churn-agent-a3f
        name:
          type: string
          description: Display name of the workflow. Shown in the builder and in run logs.
          example: Customer Churn Analyzer
        description:
          type: string
          description: Optional one-paragraph description of what this workflow does.
          example: Predicts churn risk for a customer given a 90-day usage window.
          nullable: true
        status:
          description: >-
            Lifecycle status. `draft` = never deployed. `active` = deployed.
            `deleted` = soft-deleted.
          example: active
          allOf:
            - $ref: '#/components/schemas/ResourceLifecycleStatus'
        type:
          description: >-
            Type of workflow. `task` = single-step scope orchestration;
            `workflow` = multi-step graph.
          example: task
          allOf:
            - $ref: '#/components/schemas/AgentType'
        orgUuid:
          type: string
          description: Org UUID this workflow belongs to. Matches the caller’s principal.
          example: 00000000-0000-0000-0000-000000000001
        activeVariationId:
          type: string
          description: >-
            Active (deployed) variation id. Null until the workflow is first
            deployed.
          example: 00000000-0000-4000-a000-000000000100
          nullable: true
        draftVariationId:
          type: string
          description: Most recent draft variation id. Null when there is no draft pending.
          example: 00000000-0000-4000-a000-000000000101
          nullable: true
        hasUnpublishedChanges:
          type: boolean
          description: >-
            True when the draft variation differs from the active variation
            (deploy would publish changes).
          example: false
        isEnabled:
          type: boolean
          description: >-
            Whether the workflow’s schedule is currently active. Toggle via POST
            /api/v1/workflows/{id}/toggle.
          example: true
        accessConfig:
          description: >-
            Access configuration — who in the org can use / manage this
            workflow.
          allOf:
            - $ref: '#/components/schemas/AgentAccessConfigDto'
        pendingOwnershipTransfer:
          description: >-
            Pending ownership transfer awaiting recipient acceptance. Absent
            when no request is in flight.
          nullable: true
          type: object
          allOf:
            - $ref: '#/components/schemas/PendingOwnershipTransferDto'
        variation:
          description: >-
            Variation-detail payload (`trigger`, `workflowStructure`,
            `agentSelection`) for the requested view. Populated by `GET
            /api/v1/workflows/:id`; absent on list rows.
          allOf:
            - $ref: '#/components/schemas/AgentVariationDto'
        createdAt:
          type: string
          description: Creation timestamp.
          example: '2026-05-01T10:00:00.000Z'
        updatedAt:
          type: string
          description: Most recent update timestamp.
          example: '2026-05-11T10:00:00.000Z'
        deletedAt:
          type: string
          description: Soft-delete timestamp. Null for active workflows.
          example: null
          nullable: true
        canManage:
          type: boolean
          description: >-
            Whether the requesting principal can manage
            (edit/delete/deploy/toggle) this workflow. Derived server-side from
            the principal + accessConfig. Always present on every Workflow
            response.
          example: true
        canUse:
          type: boolean
          description: >-
            Whether the requesting principal can use (run, view history of) this
            workflow. Derived server-side from the principal + accessConfig.
            Always present on every Workflow response.
          example: true
        manageDenial:
          type: string
          enum:
            - not_owner
            - needs_group_manage
          nullable: true
          description: >-
            Why `canManage` is false, for client-facing guidance:
            `needs_group_manage` (shared, but no group you belong to grants
            Manage) or `not_owner` (private, and you are not the owner). `null`
            when `canManage` is true. Derived server-side from the principal +
            accessConfig.
          example: needs_group_manage
      required:
        - id
        - slug
        - name
        - status
        - type
        - orgUuid
        - hasUnpublishedChanges
        - isEnabled
        - accessConfig
        - createdAt
        - updatedAt
        - canManage
        - canUse
        - manageDenial
    ErrorResponseDto:
      type: object
      properties:
        error:
          $ref: '#/components/schemas/ErrorEnvelopeDto'
      required:
        - error
    AgentType:
      type: string
      enum:
        - task
        - workflow
      description: >-
        Type of workflow. `task` = single-step scope orchestration; `workflow` =
        multi-step graph.
    TriggerDto:
      type: object
      properties:
        trigger_type:
          type: string
          enum:
            - schedule
            - webhook
            - api
            - slack
            - manual
          description: >-
            Trigger kind. Only `schedule` validates its nested payload here; the
            rest are opaque.
          example: schedule
        schedule:
          description: Schedule details. Required when trigger_type=schedule.
          allOf:
            - $ref: '#/components/schemas/TriggerScheduleDto'
      required:
        - trigger_type
    AgentSelectionDto:
      type: object
      properties:
        model:
          type: string
          description: Override model name for the orchestration step.
        modelSettings:
          description: >-
            Model-specific runtime controls such as reasoning effort and context
            window.
          allOf:
            - $ref: '#/components/schemas/ModelSettingsDto'
        agents:
          description: Ordered list of scopes to invoke. Must contain at least one entry.
          type: array
          items:
            $ref: '#/components/schemas/AgentSelectionEntryDto'
      required:
        - agents
    WorkflowStructureDto:
      type: object
      properties:
        nodes:
          description: Workflow nodes. Defaults to `[]`.
          type: array
          items:
            $ref: '#/components/schemas/WorkflowNodeDto'
        edges:
          description: Directed edges connecting the nodes. Defaults to `[]`.
          type: array
          items:
            $ref: '#/components/schemas/WorkflowEdgeDto'
    AgentAccessConfigDto:
      type: object
      properties:
        visibility:
          type: string
          description: >-
            Visibility tier. `shared` applies the group-permission map;
            `private` ignores groups and uses owner + sharedWith for access.
          enum:
            - shared
            - private
          example: shared
        groupPermissions:
          type: object
          description: >-
            Map of group UUID -> { use, manage } booleans. Empty object when
            visibility is `private`.
          example:
            group_eng_uuid:
              use: true
              manage: false
          additionalProperties:
            $ref: '#/components/schemas/AgentGroupPermissionDto'
        sharedWith:
          description: Per-user share entries used for private-visibility workflows.
          example: []
          type: array
          items:
            $ref: '#/components/schemas/AgentSharedUserDto'
        ownerUserId:
          type: string
          description: >-
            Clerk user id of the workflow owner. Set on first write for private
            workflows.
          example: user_2abc
          nullable: true
        ownerEmail:
          type: string
          description: >-
            Lowercased email of the workflow owner. Used by private-workflow ACL
            when owner email matches.
          example: alice@example.com
          nullable: true
      required:
        - visibility
        - groupPermissions
        - sharedWith
    ResourceLifecycleStatus:
      type: string
      enum:
        - draft
        - active
        - deleted
      description: >-
        Lifecycle status. `draft` = never deployed. `active` = deployed.
        `deleted` = soft-deleted.
    PendingOwnershipTransferDto:
      type: object
      properties:
        pendingOwnerUserId:
          type: string
          description: >-
            Clerk user id of the org member who will become owner once they
            accept.
          example: user_2abc123def456
        pendingOwnerEmail:
          type: string
          description: >-
            Email of the pending recipient, resolved from org membership at
            request time.
          example: newowner@example.com
          nullable: true
        requestedByUserId:
          type: string
          description: >-
            Clerk user id of the member who requested the transfer (the current
            owner).
          example: user_2xyz789ghi012
        requestedAt:
          type: string
          description: When the transfer was requested.
          example: '2026-06-05T12:00:00.000Z'
      required:
        - pendingOwnerUserId
        - requestedByUserId
        - requestedAt
    AgentVariationDto:
      type: object
      properties:
        trigger:
          type: object
          description: >-
            `{trigger_type, schedule?}` blob. `trigger_type` is one of `schedule
            | webhook | api | slack | manual`.
          additionalProperties: true
          nullable: true
        workflowStructure:
          type: object
          description: >-
            Workflow graph (`{nodes, edges}`) when `type` is `workflow`. Null
            when `type` is `task`.
          additionalProperties: true
          nullable: true
        agentSelection:
          type: object
          description: >-
            Selected scopes + per-step config (`{agents, model?}`) when `type`
            is `task`. Null when `type` is `workflow`.
          additionalProperties: true
          nullable: true
    ErrorEnvelopeDto:
      type: object
      properties:
        code:
          description: Modus-specific machine code.
          allOf:
            - $ref: '#/components/schemas/ApiErrorCode'
        status:
          description: Canonical status string for the error.
          allOf:
            - $ref: '#/components/schemas/ApiErrorStatus'
        message:
          type: string
          example: Skill was not found or you lack permission.
        requestId:
          type: string
          example: req_01HQ7K8ABCDEFGHIJKLMNOPQRS
        info:
          type: object
          description: >-
            Optional domain-specific context. Shape varies per endpoint — see
            the operation's error response examples.
          additionalProperties: true
          example:
            skillId: sk_abc123
      required:
        - code
        - status
        - message
        - requestId
    TriggerScheduleDto:
      type: object
      properties:
        frequency:
          type: string
          enum:
            - hourly
            - daily
            - weekly
            - monthly
            - custom
          description: Cadence of the schedule.
          example: daily
        time_of_day:
          type: string
          description: >-
            Time of day in 24-hour HH:MM format. Required for
            hourly/daily/weekly/monthly; ignored for custom.
          example: '09:00'
          pattern: ^([01]\d|2[0-3]):[0-5]\d$
        timezone:
          type: string
          description: IANA timezone identifier.
          example: UTC
        weekdays:
          type: array
          description: Required for weekly schedules. Lowercase day names.
          example:
            - monday
            - wednesday
            - friday
          items:
            type: string
            enum:
              - monday
              - tuesday
              - wednesday
              - thursday
              - friday
              - saturday
              - sunday
        day_of_month:
          type: number
          description: Required for monthly schedules. Calendar day 1-31.
          example: 15
          minimum: 1
          maximum: 31
        cron_expressions:
          description: >-
            Required for custom schedules. Each entry is a 5-field POSIX cron
            expression.
          example:
            - 0 9 * * 1-5
          type: array
          items:
            type: string
        cron_description:
          type: string
          description: >-
            Human-readable description of the custom schedule. Required when
            frequency=custom.
          example: Weekdays at 9am
      required:
        - frequency
        - timezone
    ModelSettingsDto:
      type: object
      properties:
        reasoningEffort:
          description: Optional reasoning effort for models that support it.
          allOf:
            - $ref: '#/components/schemas/ReasoningEffort'
        contextWindow:
          type: number
          description: Selected model context window in tokens.
          minimum: 1
    AgentSelectionEntryDto:
      type: object
      properties:
        agent_id:
          type: number
          description: Numeric scope (workflow) id to invoke at this step.
          example: 17
          minimum: 1
        priority_order:
          type: number
          description: Execution order (1-indexed).
          example: 1
          minimum: 1
        role:
          type: string
          description: Optional role label.
          example: researcher
        instructions:
          type: string
          description: Per-step instructions added to the prompt.
          example: Focus on the last 30 days of data
        tool_restrictions:
          description: Optional allowlist of tools the step may call.
          type: array
          items:
            type: string
      required:
        - agent_id
        - priority_order
    WorkflowNodeDto:
      type: object
      properties:
        id:
          type: string
          description: Stable node id, unique within the graph.
          example: '1'
        type:
          description: Node kind. Determines how the runtime interprets `data`.
          example: start
          allOf:
            - $ref: '#/components/schemas/WorkflowNodeType'
        position:
          description: >-
            Canvas position. Optional — preserved for builder layout when
            present.
          allOf:
            - $ref: '#/components/schemas/WorkflowNodePositionDto'
        data:
          type: object
          additionalProperties: true
          description: >-
            Node-type-specific payload (intentionally open — shape varies by
            `type`). Defaults to `{}`.
          example: {}
      required:
        - id
        - type
    WorkflowEdgeDto:
      type: object
      properties:
        id:
          type: string
          description: Stable edge id, unique within the graph.
          example: e1
        source:
          type: string
          description: Source node id.
          example: '1'
        target:
          type: string
          description: Target node id.
          example: '2'
        sourceHandle:
          type: string
          description: >-
            Source port handle (e.g. a condition branch). Omit for a
            single-output node.
          example: branch_0
      required:
        - id
        - source
        - target
    AgentGroupPermissionDto:
      type: object
      properties:
        use:
          type: boolean
          description: Whether members of this group may use (run / invoke) the workflow.
          example: true
        manage:
          type: boolean
          description: >-
            Whether members of this group may manage (edit / deploy / delete)
            the workflow.
          example: false
      required:
        - use
        - manage
    AgentSharedUserDto:
      type: object
      properties:
        email:
          type: string
          description: >-
            Lowercased email of a user explicitly granted access to a private
            workflow.
          example: alice@example.com
        addedAt:
          type: string
          description: ISO-8601 timestamp at which this user was added to the share list.
          example: '2026-05-01T10:00:00Z'
        addedBy:
          type: string
          description: Clerk user id of the principal that added this share entry.
          example: user_2abc
        userId:
          type: string
          description: >-
            Clerk user id of the invited principal (optional — email is the
            primary key).
          example: user_2xyz
      required:
        - email
    ApiErrorCode:
      type: string
      enum:
        - VALIDATION
        - BAD_REQUEST
        - UNAUTHORIZED
        - FORBIDDEN
        - NOT_FOUND
        - CONFLICT
        - RATE_LIMITED
        - INTERNAL_ERROR
      description: Modus-specific machine code.
    ApiErrorStatus:
      type: string
      enum:
        - INVALID_ARGUMENT
        - UNAUTHENTICATED
        - PERMISSION_DENIED
        - NOT_FOUND
        - ALREADY_EXISTS
        - RESOURCE_EXHAUSTED
        - INTERNAL
      description: Canonical status string for the error.
    ReasoningEffort:
      type: string
      enum:
        - none
        - minimal
        - low
        - medium
        - high
        - xhigh
        - max
      description: Optional reasoning effort for models that support it.
    WorkflowNodeType:
      type: string
      enum:
        - start
        - action
        - condition
        - agent
        - humanApproval
      description: Node kind. Determines how the runtime interprets `data`.
    WorkflowNodePositionDto:
      type: object
      properties:
        x:
          type: number
          example: 0
        'y':
          type: number
          example: 50
      required:
        - x
        - 'y'
  securitySchemes:
    bearerAuth:
      scheme: bearer
      bearerFormat: Modus PAT (modus_<orgUuid>_<prefix>_<secret>) or OAuth 2.1 access token
      type: http
      description: >-
        A Modus personal access token (`modus_<orgUuid>_<prefix>_<secret>`) or
        an OAuth 2.1 access token, sent as `Authorization: Bearer <token>`.

````