Eval runs

Enable, repoint, or disable a suite's schedule

A schedule fires exactly ONE run per interval, so an environment-based suite must pin exactly one of its attached environments. Omitting environmentId on a single-environment suite means that environment; omitting it on a multi-environment suite is a VALIDATION_ERROR. Disabling preserves the existing pin. Responds with the full updated suite.

patch/projects/{projectId}/eval-suites/{suiteId}/schedule

Path parameters

projectIdstring required

ID of the hosted project that contains the server.

suiteIdstring required

Eval suite ID, as returned by POST /eval-runs.

Query parameters

declaredSuiteIdstring

The suite file's own suite.id, when this request is that file syncing itself. A CI-owned suite (see EvalSuiteDetail.managedBy) refuses configuration writes with 409 and details.reason: "CI_OWNED_SUITE_READ_ONLY"; naming the suite's own declared id is how the file writing itself is allowed through. Naming any other id refuses exactly as loudly as naming none, so it is not a capability — omit it for an ordinary edit.

A QUERY PARAMETER on every route that takes it, never a body field. These request bodies are strict, here and on every Inspector that predates the CI-owned lock, so a body field is a 400 against an older deployment — which would break mcpjam cloud eval run --file for anyone whose CLI is newer than their Inspector. A query parameter is read by the deployments that know it and ignored by those that do not, which is the right degradation: an Inspector with no lock has no exception to make.

Headers

x-mcpjam-eval-vocabulary'1' | '2'

Which vocabulary this request and its response speak. Absent means 1, which is byte-for-byte today's contract: the same request fields, the same refusals, the same response projection. 2 is the canonical vocabulary. Any other value is a 400 with code: "VALIDATION_ERROR".

Today it decides one thing: the spelling of an evaluator's policy role. Vocabulary 1 accepts and returns gating; vocabulary 2 accepts both spellings and returns the canonical required. Sending required without the header is a 400, deliberately — vocabulary 1 is not widened to meet vocabulary 2 half way, because a boundary that accepts a spelling it does not announce is one two implementations can disagree about.

A response that varies by vocabulary sends Vary: x-mcpjam-eval-vocabulary.

Request body

declaredSuiteIdstring

The suite file's own suite.id, when THIS request is a suite-file sync.

A CI-owned suite (see EvalSuiteDetail.managedBy) refuses configuration writes with 409 and details.reason: "CI_OWNED_SUITE_READ_ONLY". Naming the suite's own declared id is how the file writing itself is allowed through — the platform permits the write only when the id matches, so naming any other id refuses exactly as loudly as naming none. Omit it for ordinary edits.

PREFER THE declaredSuiteId QUERY PARAMETER on this route. This body field still works here, but these request bodies are strict on every Inspector that predates the CI-owned lock, so a body field is a 400 against an older deployment while an unknown query parameter is simply ignored. The MCPJam SDK and CLI send the query parameter.

enabledboolean required
intervalMinutesinteger
environmentIdstring

Which attached environment scheduled runs use. Only meaningful when enabling. Omitted on a single-environment suite means that environment; omitted on a multi-environment suite is a VALIDATION_ERROR.

Response

The updated suite.

idstring required
declaredIdstring

The suite's declared file identity (suite.id in a suite file). Present on file-owned suites; absent on UI-authored suites, which have no declared id and cannot be claimed by eval run --file.

managedBy'ci' | 'app'

Where this suite's configuration lives. ci means it is owned by a committed suite file or by MCPJam SDK ingest, and the platform REFUSES configuration writes to it — name, settings, environments, schedule, models, skills, execution config and cases — from this API and from the app alike, with 409 CONFLICT and details.reason: "CI_OWNED_SUITE_READ_ONLY".

Running, replaying, comparing and DELETING are unaffected — deleting a suite is not editing one, and it is the only cleanup an SDK-created suite has. To change a CI-owned suite, either edit its file and send that file's suite.id as declaredSuiteId on the write, or duplicate the suite for an editable copy.

declaredId alone is not this answer: a suite created by SDK ingest is CI-owned and has no declared id.

namestring nullable
descriptionstring nullable
projectIdstring nullable
environmentIdsstring[]

Attached project environments, in attach order.

revisionNumberinteger nullable

How many committed edits this suite has had, or null on a deployment that does not record revisions. Send it back as expectedRevisionNumber on a PATCH to make that edit a compare-and-set.

createdAtnumber nullable

Epoch milliseconds.

updatedAtnumber nullable

Changes

Changed in 10 of the 122 revisions of this API.126

    • ○

      added the optional property / to the response with the status

      response-optional-property-added

    • ○

      the response property / became required for the status

      response-property-became-required

    • ○

      the response property / became required for the status

      response-property-became-required

    • ○

      the response property / became required for the status

      response-property-became-required

    • ○

      the response property / became required for the status

      response-property-became-required

    • ○

      added the new optional header request parameter x-mcpjam-eval-vocabulary

      new-optional-request-parameter

    • ○

      added the new optional query request parameter declaredSuiteId

      new-optional-request-parameter

    • ○

      added the new optional request property

      new-optional-request-property

    • ○

      added the optional property to the response with the status

      response-optional-property-added

    • ○

      added the optional property // to the response with the status

      response-optional-property-added

    • ○

      added the optional property // to the response with the status

      response-optional-property-added

    • ○

      added the optional property to the response with the status

      response-optional-property-added

    • ○

      added the optional property / to the response with the status

      response-optional-property-added

    • ○

      added the optional property / to the response with the status

      response-optional-property-added

    • ○

      added the optional property / to the response with the status

      response-optional-property-added

    • ○

      added the optional property / to the response with the status

      response-optional-property-added

    • ○

      added the optional property // to the response with the status

      response-optional-property-added

    • ○

      added the optional property / to the response with the status

      response-optional-property-added

    • ○

      added the optional property / to the response with the status

      response-optional-property-added

    • ○

      added the optional property / to the response with the status

      response-optional-property-added

    • ○

      added the optional property to the response with the status

      response-optional-property-added

    • ○

      added the optional property / to the response with the status

      response-optional-property-added

    • ○

      added the optional property // to the response with the status

      response-optional-property-added

    • ○

      added the optional property // to the response with the status

      response-optional-property-added

    • ○

      added the optional property / to the response with the status

      response-optional-property-added

    • ▲

      the response property became optional for the status

      response-property-became-optional

    • ○

      endpoint added

      endpoint-added