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

# Compact an objective

> Summarize a conversation and start a fresh context window on demand, before the threshold forces it.

An objective compacts on its own when its context window crosses the variation's `triggerThreshold`. This endpoint lets you do it early, and lets you steer what the summary keeps.

Reach for it before an expensive turn, or when you want a clean window before handing the conversation somewhere new.

<Warning>
  **Only compact an objective in `STATE_WAITING`.**

  Compacting a `STATE_PENDING` or `STATE_RUNNING` objective returns `200` and permanently stops it. The objective stays `STATE_RUNNING` forever, produces no further events, and does not respond to [cancel](/docs/api-reference/objectiveservice/cancel-an-objective). There is no precondition check and no way to recover the run.

  Check the state first. Unlike [continue](/docs/api-reference/objectiveservice/continue-an-objective), which rejects a mid-turn objective with a `400`, this endpoint accepts the call and swallows the objective.
</Warning>

## Compact a waiting objective

<CodeGroup>
  ```typescript TypeScript theme={null}
  const objective = await client.objectives.retrieve(objectiveId, { workspaceId });
  if (objective.state !== 'STATE_WAITING') throw new Error(`refusing to compact: ${objective.state}`);

  await client.objectives.compact(objectiveId, { workspaceId });
  ```

  ```go Go theme={null}
  objective, err := client.Objectives.Get(ctx, objectiveID,
  	cadenya.ObjectiveGetParams{WorkspaceID: cadenya.String(workspaceID)})
  if err != nil {
  	log.Fatal(err)
  }
  if objective.State != "STATE_WAITING" {
  	log.Fatalf("refusing to compact: %s", objective.State)
  }

  _, err = client.Objectives.Compact(ctx, objectiveID,
  	cadenya.ObjectiveCompactParams{WorkspaceID: cadenya.String(workspaceID)})
  ```

  ```ruby Ruby theme={null}
  objective = cadenya.objectives.retrieve(objective_id, workspace_id: workspace_id)
  raise "refusing to compact: #{objective.state}" unless objective.state == :STATE_WAITING

  cadenya.objectives.compact(objective_id, workspace_id: workspace_id)
  ```

  ```bash cURL theme={null}
  # Check the state first: compacting a running objective swallows it.
  curl "https://api.cadenya.com/v1/workspaces/${WORKSPACE_ID}/objectives/${OBJECTIVE_ID}" \
    -H "Authorization: Bearer ${CADENYA_API_KEY}"

  curl -X POST "https://api.cadenya.com/v1/workspaces/${WORKSPACE_ID}/objectives/${OBJECTIVE_ID}:compact" \
    -H "Authorization: Bearer ${CADENYA_API_KEY}" \
    -H "Content-Type: application/json" \
    -d '{}'
  ```
</CodeGroup>

The objective stays `STATE_WAITING` and remains continuable. A `contextWindowCompacted` event fires, a new window opens at `sequence: 2`, and the summary of everything before it is carried forward.

<Note>
  `CompactObjectiveResponse` declares a `contextWindow` field. The response body is `{}` in practice. Read the new window from [List context windows](/docs/api-reference/objectiveservice/list-objective-context-windows) instead.
</Note>

## Steer what survives

Pass a `compactionConfig` and it overrides the variation's, for this compaction only.

```typescript theme={null}
await client.objectives.compact(objectiveId, {
  workspaceId,
  compactionConfig: {
    summarization: { instructions: 'Keep every decision and open question. Drop the tool chatter.' },
    toolResultClearing: { preserveRecentResults: 2 },
  },
});
```

Summarization always runs, on the variation's own model, so a compaction is a billed model call. `toolResultClearing` is an optional pre-pass that shrinks what the summarizer has to read; it does not replace it.

The summary lands on the new window as `previousWindowContinueInstructions`, and it populates **asynchronously**: read the window immediately after compacting and the field is empty, then a few seconds later it holds the summary.

```typescript theme={null}
await client.objectives.compact(objectiveId, { workspaceId });

// A moment later:
const [newest] = (await client.objectives.listContextWindows(objectiveId, { workspaceId })).items;
console.log(newest.data.previousWindowContinueInstructions);
// **Task:** User requested a fake company name.
//
// **Completed:** Used the faker tool (GetFake...
```

That text is the objective's whole memory of everything before the compaction. When the agent forgets something afterward, the summary dropped it, and `instructions` is the lever.

## When to compact by hand

Automatic compaction fires at `triggerThreshold`, a fraction of the model's `maxInputTokens`. That is the right default, and most agents never need this endpoint.

Manual compaction earns its keep in three places:

* **Before an expensive turn.** The next message pulls a large document into the window. Compact first so it fits.
* **At a topic boundary.** A support conversation moves from diagnosis to billing. Compact with instructions that keep the diagnosis conclusion and drop the transcript.
* **Before handing off.** Another system is about to take the conversation. A compacted window is a smaller, cheaper thing to continue.

Compaction is lossy on purpose. Each one replaces detail with a summary, so compacting on a timer costs you fidelity and a model call for nothing.

## Related

<CardGroup cols={2}>
  <Card title="List context windows" icon="layer-group" href="/docs/api-reference/objectiveservice/list-objective-context-windows">
    The new window, its token counts, and the summary it carried in.
  </Card>

  <Card title="Create a variation" icon="sliders" href="/docs/api-reference/agentvariationservice/create-a-new-variation">
    `triggerThreshold`, summarization instructions, and tool result clearing.
  </Card>

  <Card title="Continue an objective" icon="comments" href="/docs/api-reference/objectiveservice/continue-an-objective">
    The next turn, which reads the summary you produced.
  </Card>

  <Card title="Get objective diagnostics" icon="magnifying-glass-chart" href="/docs/api-reference/objectiveservice/get-objective-context-diagnostics">
    How full the window is right now.
  </Card>
</CardGroup>


## OpenAPI

````yaml post /v1/workspaces/{workspaceId}/objectives/{objectiveId}:compact
openapi: 3.1.0
info:
  title: Cadenya API
  description: API for the Cadenya Agent Runtime platform.
  version: '1.0'
servers:
  - url: https://api.cadenya.com
    description: Production server
security:
  - bearerAuth: []
tags:
  - name: AIProviderKeyService
  - name: APIKeyService
    description: |-
      Issue, rotate, disable, and revoke a workspace's API keys. Every key
       belongs to exactly one workspace; the system-managed global account key is
       managed via GlobalAPIKeyService instead.
  - name: AccountService
    description: >-
      Manage the authenticated account. Accounts are the top-level
      organizational
       unit and contain one or more workspaces.
  - name: AgentScheduleService
    description: >-
      Manage recurring schedules attached to agents. Schedules trigger
      objectives
       on a cadence defined by AgentScheduleSpec.Schedule.
  - name: AgentService
    description: >-
      Manage AI agents within a workspace. Agents define AI behavior and tool
      access.
  - name: AgentVariationService
    description: >-
      Manage variations of an agent and their tool, sub-agent, and memory layer
      assignments.
  - name: GlobalAPIKeyService
    description: |-
      Manage the account's system-provisioned global API key. The global key is
       the only key that spans every workspace; it is created by the system and
       cannot be deleted, so the surface is retrieve, rotate, and the
       disable/enable kill switch.
  - name: MemoryService
    description: >-
      Manage memory layers and their entries. Layers are named containers that
      can
       be composed into an objective's memory cascade; entries are the keyed values
       within a layer. System-managed layers (e.g., episodic layers created by the
       runtime) cannot be mutated through this API.
  - name: ModelService
    description: |-
      Manage LLM models available to a workspace. Models represent provider and
       family pairs (e.g., "anthropic/claude-sonnet-4.6"). Workspaces are seeded
       with the supported models and you can enable or disable each one.
  - name: ObjectiveEventStreamsService
  - name: ObjectiveService
  - name: ProfilesService
    description: |-
      Operations on profiles, the account-level principals (users, API keys,
       system) that authenticate against the API.
  - name: SearchService
  - name: TenantService
    description: >-
      Read and erase tenants and the subjects under them. Tenants and subjects
      are
       created by assertion — on objective creation or widget session mint — never
       directly, so this service has no create or update: it exists to enumerate what
       assertions have produced, and to destroy it on request.
  - name: ToolService
    description: >-
      Manage tool sets and the tools they contain. Tool sets group related
      tools,
       and tools define specific capabilities available to agents.

       When a tool set is managed, only API key actors can modify its tools; human
       (profile) actors cannot.
  - name: UploadService
    description: |-
      Issue short-lived presigned URLs for direct client-to-object-storage
       uploads. Created uploads can be referenced by id when creating or updating
       resources that accept binary content (e.g., MemoryEntry).
  - name: WidgetService
    description: |-
      Manage embeddable chat widgets. A widget binds an agent to a globally
       unique hostname with a per-widget origin allowlist; browsers reach it with
       session tokens minted via WidgetSessionService.
  - name: WidgetSessionService
    description: >-
      Mint and manage widget sessions. Session creation is server-to-server
      only:
       the customer's backend authenticates its visitor, asserts tenant/subject
       context, attaches any per-visitor secrets, and receives a short-lived
       bearer token the browser uses against the widget host.
  - name: WorkspaceAdminService
    description: >-
      Administer workspaces across the account: create and archive workspaces
      and
       manage their membership. These operations are account-scoped and require the
       admin role (a token whose profile holds the WorkOS admin role); they live
       under /v1/account/workspaces rather than the workspace-scoped /v1/workspaces
       tree so an admin can manage any workspace in the account, including ones they
       are not themselves a member of.
  - name: WorkspaceSecretService
  - name: WorkspaceService
    description: |-
      Manage workspaces within an account. Workspaces provide organizational
       grouping and isolation for resources such as agents, tools, and API keys.

       This is the workspace-scoped, end-user surface. Administrative operations
       (create / archive workspaces, manage members) live in WorkspaceAdminService
       under /v1/account/workspaces and require the admin role.
paths:
  /v1/workspaces/{workspaceId}/objectives/{objectiveId}:compact:
    post:
      tags:
        - ObjectiveService
        - Objectives
      summary: Compact an objective
      description: >-
        Triggers compaction on a running objective. Optionally override the
        variation's compaction config.
      operationId: ObjectiveService_CompactObjective
      parameters:
        - name: workspaceId
          in: path
          required: true
          schema:
            type: string
            example: workspace_01HXKD2E5NQM3T9AYWCF133E3Q
        - name: objectiveId
          in: path
          description: >-
            The ID of the objective. Supports "external_id:" prefix for external
            IDs.
          required: true
          schema:
            example: obj_01HXKD2E5NQM3T9AYWCFQAZGFV
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CompactObjectiveRequest'
        required: true
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CompactObjectiveResponse'
        default:
          description: Default error response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Status'
      x-codeSamples:
        - lang: JavaScript
          source: >-
            import Cadenya from '@cadenya/cadenya';


            const client = new Cadenya({
              apiKey: process.env['CADENYA_API_KEY'], // This is the default and can be omitted
            });


            const response = await
            client.objectives.compact('obj_01HXKD2E5NQM3T9AYWCFQAZGFV', {
              workspaceId: 'workspace_01HXKD2E5NQM3T9AYWCF133E3Q',
            });


            console.log(response.contextWindow);
        - lang: Python
          source: |-
            import os
            from cadenya import Cadenya

            client = Cadenya(
                api_key=os.environ.get("CADENYA_API_KEY"),  # This is the default and can be omitted
            )
            response = client.objectives.compact(
                objective_id="obj_01HXKD2E5NQM3T9AYWCFQAZGFV",
                workspace_id="workspace_01HXKD2E5NQM3T9AYWCF133E3Q",
            )
            print(response.context_window)
        - lang: Go
          source: "package main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"go.cadenya.com/cadenya-go\"\n\t\"go.cadenya.com/cadenya-go/option\"\n)\n\nfunc main() {\n\tclient := cadenya.NewClient(\n\t\toption.WithAPIKey(\"My API Key\"),\n\t)\n\tresponse, err := client.Objectives.Compact(\n\t\tcontext.TODO(),\n\t\t\"obj_01HXKD2E5NQM3T9AYWCFQAZGFV\",\n\t\tcadenya.ObjectiveCompactParams{\n\t\t\tWorkspaceID: cadenya.String(\"workspace_01HXKD2E5NQM3T9AYWCF133E3Q\"),\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf(\"%+v\\n\", response.ContextWindow)\n}\n"
        - lang: Ruby
          source: |-
            require "cadenya"

            cadenya = Cadenya::Client.new(api_key: "My API Key")

            response = cadenya.objectives.compact(
              "obj_01HXKD2E5NQM3T9AYWCFQAZGFV",
              workspace_id: "workspace_01HXKD2E5NQM3T9AYWCF133E3Q"
            )

            puts(response)
        - lang: CLI
          source: |-
            cadenya objectives compact \
              --api-key 'My API Key' \
              --workspace-id workspace_01HXKD2E5NQM3T9AYWCF133E3Q \
              --objective-id obj_01HXKD2E5NQM3T9AYWCFQAZGFV
components:
  schemas:
    CompactObjectiveRequest:
      type: object
      properties:
        workspaceId:
          readOnly: true
          example: workspace_01HXKD2E5NQM3T9AYWCF133E3Q
          type: string
        objectiveId:
          readOnly: true
          example: obj_01HXKD2E5NQM3T9AYWCFQAZGFV
          type: string
          description: >-
            The ID of the objective. Supports "external_id:" prefix for external
            IDs.
        compactionConfig:
          allOf:
            - $ref: '#/components/schemas/AgentVariationSpec_CompactionConfig'
          description: >-
            Optional compaction config override. When not set, uses the
            variation's compaction_config.
      description: Compact objective request — triggers compaction on a running objective.
    CompactObjectiveResponse:
      type: object
      properties:
        contextWindow:
          allOf:
            - $ref: '#/components/schemas/ObjectiveContextWindowData'
          description: The new context window created by the compaction
      description: Compact objective response
    Status:
      type: object
      properties:
        code:
          type: integer
          description: >-
            The status code, which should be an enum value of
            [google.rpc.Code][google.rpc.Code].
          format: int32
        message:
          type: string
          description: >-
            A developer-facing error message, which should be in English. Any
            user-facing error message should be localized and sent in the
            [google.rpc.Status.details][google.rpc.Status.details] field, or
            localized by the client.
        details:
          type: array
          items:
            $ref: '#/components/schemas/GoogleProtobufAny'
          description: >-
            A list of messages that carry the error details.  There is a common
            set of message types for APIs to use.
      description: >-
        The `Status` type defines a logical error model that is suitable for
        different programming environments, including REST APIs and RPC APIs. It
        is used by [gRPC](https://github.com/grpc). Each `Status` message
        contains three pieces of data: error code, error message, and error
        details. You can find out more about this error model and how to work
        with it in the [API Design
        Guide](https://cloud.google.com/apis/design/errors).
    AgentVariationSpec_CompactionConfig:
      type: object
      properties:
        triggerThreshold:
          type: number
          description: >-
            Trigger threshold as a percentage of the model's context window (0.0
            to 1.0).
             When input tokens reach this percentage of the model's limit, compaction triggers.
             Default: 0.75 (75%)
          format: float
        summarization:
          allOf:
            - $ref: '#/components/schemas/CompactionConfig_SummarizationStrategy'
          description: >-
            Strategies — set one or more. When multiple are set, they execute in
            order:
             tool_result_clearing → summarization.
             When none are set, defaults to summarization with the system default prompt.
        toolResultClearing:
          $ref: '#/components/schemas/CompactionConfig_ToolResultClearingStrategy'
      description: >-
        CompactionConfig defines how context window compaction behaves for
        objectives using this variation.
    ObjectiveContextWindowData:
      type: object
      properties:
        objectiveId:
          readOnly: true
          example: obj_01HXKD2E5NQM3T9AYWCFQAZGFV
          type: string
          description: The objective's ID that this window belongs to
        sequence:
          readOnly: true
          type: integer
          description: >-
            sequence is a numeric representation of which context window this
            is. Sequences are useful to perform a max(sequence) on in order
             to calculate how many context windows an objective has.
          format: int32
        promptTokens:
          readOnly: true
          type: integer
          description: >-
            A calculated value for how many prompt tokens (input tokens) have
            been used in this context window
          format: int32
        completionTokens:
          readOnly: true
          type: integer
          description: >-
            A calculated value for how many completion tokens (output tokens)
            have been used in this context window
          format: int32
        previousWindowContinueInstructions:
          type: string
          description: >-
            The instructions for this window to continue from a previous
            window's chat history.
    GoogleProtobufAny:
      type: object
      properties:
        '@type':
          type: string
          description: The type of the serialized message.
      additionalProperties: true
      description: >-
        Contains an arbitrary serialized message along with a @type that
        describes the type of the serialized message.
    CompactionConfig_SummarizationStrategy:
      type: object
      properties:
        instructions:
          type: string
          description: |-
            Custom instructions that guide what the summarizer preserves.
             Replaces the default summarization prompt entirely.
             Example: "Preserve all code snippets, variable names, and technical decisions."
      description: >-
        SummarizationStrategy configures LLM-powered summarization of older
        conversation turns.
    CompactionConfig_ToolResultClearingStrategy:
      type: object
      properties:
        preserveRecentResults:
          type: integer
          description: |-
            Number of most recent tool call results to keep intact.
             Older tool results have their content replaced with "[result cleared]"
             while preserving the assistant tool call message (function name, arguments).
             Default: 2
          format: int32
      description: >-
        ToolResultClearingStrategy configures clearing of older tool result
        content.
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT

````