> ## 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.

# List objective context windows

> Every window an objective has burned through, with the token counts and the summary each one handed to the next.

An objective starts with one context window. When it fills past the [compaction](/docs/api-reference/agentvariationservice/create-a-new-variation) threshold, Cadenya opens a fresh one and carries a summary forward. This endpoint is the record of that: what each window cost, and what survived the handoff.

It is also the only token history that outlives the objective.

<CodeGroup>
  ```typescript TypeScript theme={null}
  const windows = await client.objectives.listContextWindows(objectiveId, { workspaceId });

  for await (const w of windows) {
    console.log(w.data.sequence, w.data.promptTokens, w.data.completionTokens);
  }
  // 2  3345  255
  // 1  8718  478
  ```

  ```go Go theme={null}
  windows := client.Objectives.ListContextWindowsAutoPaging(ctx, objectiveID,
  	cadenya.ObjectiveListContextWindowsParams{WorkspaceID: cadenya.String(workspaceID)})

  for windows.Next() {
  	w := windows.Current()
  	fmt.Println(w.Data.Sequence, w.Data.PromptTokens, w.Data.CompletionTokens)
  }
  // 2  3345  255
  // 1  8718  478
  ```

  ```ruby Ruby theme={null}
  windows = cadenya.objectives.list_context_windows(objective_id, workspace_id: workspace_id)

  windows.auto_paging_each do |w|
    puts [w.data.sequence, w.data.prompt_tokens, w.data.completion_tokens].join("  ")
  end
  # 2  3345  255
  # 1  8718  478
  ```

  ```bash cURL theme={null}
  curl "https://api.cadenya.com/v1/workspaces/${WORKSPACE_ID}/objectives/${OBJECTIVE_ID}/context_windows" \
    -H "Authorization: Bearer ${CADENYA_API_KEY}"
  ```
</CodeGroup>

Windows come back **newest first**, and the endpoint returns at most the **last five**. A long objective that compacted a dozen times has lost the early ones.

## Reading a compaction

That output is a real compaction, and it tells the whole story. Window 1 grew to 8,718 prompt tokens. It crossed the threshold, so Cadenya summarized it, opened window 2, and window 2 restarted at 3,345 prompt tokens.

The summary itself is on the new window, as `previousWindowContinueInstructions`:

```typescript theme={null}
const [newest] = (await client.objectives.listContextWindows(objectiveId, { workspaceId })).items;

console.log(newest.data.previousWindowContinueInstructions);
// ## Conversation Summary
//
// **Task:** User requested a generated fake name and address.
//
// **Actions Taken:**
// 1. Qu...
```

The first window's `previousWindowContinueInstructions` is empty, because nothing preceded it. That is how you tell the original window from a compacted one: `sequence: 1` with no instructions.

Read the summary when an agent seems to forget something mid-objective. Compaction is lossy by design, and this field is exactly what it chose to keep. If the thing the agent lost is missing here, tune `summarization.instructions` on the variation.

## Use it for the post-mortem

[Objective diagnostics](/docs/api-reference/objectiveservice/get-objective-context-diagnostics) gives a much richer breakdown, per component, but only while the objective is live. Every terminal objective reports zeros there.

Context windows persist. The same `STATE_TIMED_OUT` objective that reports `inputTokens: 0` from diagnostics still reports `promptTokens: 34653` here.

| Question                             | Endpoint                                                                         |
| ------------------------------------ | -------------------------------------------------------------------------------- |
| Where is my window going, right now? | [Diagnostics](/docs/api-reference/objectiveservice/get-objective-context-diagnostics) |
| What did this finished run cost?     | This one                                                                         |
| How many times did it compact?       | This one, or `info.totalContextWindows`                                          |
| What did compaction throw away?      | `previousWindowContinueInstructions`                                             |

```typescript theme={null}
const objective = await client.objectives.retrieve(objectiveId, { workspaceId, includeInfo: true });
console.log(objective.info?.totalContextWindows);   // 2
console.log(objective.info?.currentContextWindowId); // objwin_...
```

`totalContextWindows` counts every window, including any the five-window cap has aged out of this list.

## What each window carries

| Field                                | What it means                                                          |
| ------------------------------------ | ---------------------------------------------------------------------- |
| `sequence`                           | 1 for the original window, incrementing on each compaction.            |
| `promptTokens`                       | Input tokens sent to the model across this window's turns.             |
| `completionTokens`                   | Tokens the model produced.                                             |
| `previousWindowContinueInstructions` | The summary carried in from the window before. Empty on `sequence: 1`. |

Sum `promptTokens` and `completionTokens` across windows and multiply by the model's `inputPricePerMillionTokens` and `outputPricePerMillionTokens` to price a run. That is the closest thing to a per-objective invoice the API offers.

<Note>
  Compaction itself costs a model call: the summarizer runs on the variation's own model, and its usage is recorded as an iteration. A window's `promptTokens` is what the agent spent, not what compaction spent producing the summary that opened it.
</Note>

## Related

<CardGroup cols={2}>
  <Card title="Get objective diagnostics" icon="magnifying-glass-chart" href="/docs/api-reference/objectiveservice/get-objective-context-diagnostics">
    The live, component-by-component breakdown of the current window.
  </Card>

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

  <Card title="Compaction" icon="compress" href="/docs/guides/objectives#context-windows">
    Why an objective compacts instead of failing.
  </Card>

  <Card title="List models" icon="list" href="/docs/api-reference/modelservice/list-models">
    The per-million-token prices you need to turn tokens into dollars.
  </Card>
</CardGroup>


## OpenAPI

````yaml get /v1/workspaces/{workspaceId}/objectives/{objectiveId}/context_windows
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}/context_windows:
    get:
      tags:
        - ObjectiveService
        - Objectives
      summary: List objective context windows
      description: >-
        Read-only list of the last five windows of execution for this objective,
        ordered by most recent first
      operationId: ObjectiveService_ListObjectiveContextWindows
      parameters:
        - name: workspaceId
          in: path
          required: true
          schema:
            type: string
            example: workspace_01HXKD2E5NQM3T9AYWCF133E3Q
        - name: objectiveId
          in: path
          description: The objective ID to return windows for
          required: true
          schema:
            example: obj_01HXKD2E5NQM3T9AYWCFQAZGFV
            type: string
        - name: limit
          in: query
          description: Maximum number of results to return
          schema:
            type: integer
            format: int32
        - name: cursor
          in: query
          description: Pagination cursor from previous response
          schema:
            type: string
        - name: includeInfo
          in: query
          description: When set to true you may use more of your alloted API rate-limit
          schema:
            type: boolean
        - name: labels
          in: query
          description: |-
            Filters by metadata labels. Comma-separated key=value pairs,
             e.g. "env=prod,team=ai". A resource matches only if every pair
             matches exactly (AND semantics).
          schema:
            type: string
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListObjectiveContextWindowsResponse'
        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
            });


            // Automatically fetches more pages as needed.

            for await (const objectiveContextWindow of
            client.objectives.listContextWindows(
              'obj_01HXKD2E5NQM3T9AYWCFQAZGFV',
              { workspaceId: 'workspace_01HXKD2E5NQM3T9AYWCF133E3Q' },
            )) {
              console.log(objectiveContextWindow.data);
            }
        - 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
            )
            page = client.objectives.list_context_windows(
                objective_id="obj_01HXKD2E5NQM3T9AYWCFQAZGFV",
                workspace_id="workspace_01HXKD2E5NQM3T9AYWCF133E3Q",
            )
            page = page.items[0]
            print(page.data)
        - 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\tpage, err := client.Objectives.ListContextWindows(\n\t\tcontext.TODO(),\n\t\t\"obj_01HXKD2E5NQM3T9AYWCFQAZGFV\",\n\t\tcadenya.ObjectiveListContextWindowsParams{\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\", page)\n}\n"
        - lang: Ruby
          source: |-
            require "cadenya"

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

            page = cadenya.objectives.list_context_windows(
              "obj_01HXKD2E5NQM3T9AYWCFQAZGFV",
              workspace_id: "workspace_01HXKD2E5NQM3T9AYWCF133E3Q"
            )

            puts(page)
        - lang: CLI
          source: |-
            cadenya objectives list-context-windows \
              --api-key 'My API Key' \
              --workspace-id workspace_01HXKD2E5NQM3T9AYWCF133E3Q \
              --objective-id obj_01HXKD2E5NQM3T9AYWCFQAZGFV
components:
  schemas:
    ListObjectiveContextWindowsResponse:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: '#/components/schemas/ObjectiveContextWindow'
        pagination:
          $ref: '#/components/schemas/Page'
      description: >-
        ListObjectiveContextWindowsResponse is the response to a
        ListObjectiveContextWindowsRequest
    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).
    ObjectiveContextWindow:
      required:
        - metadata
        - data
      type: object
      properties:
        metadata:
          $ref: '#/components/schemas/OperationMetadata'
        data:
          $ref: '#/components/schemas/ObjectiveContextWindowData'
        info:
          $ref: '#/components/schemas/ObjectiveContextWindowInfo'
      description: >-
        ObjectiveContextWindow is a window of chat completions that is grouped
        together to prevent context-window overflows. Context windows also allow
         agents to compact their windows and carry on into a new one.
    Page:
      type: object
      properties:
        nextCursor:
          type: string
      description: >-
        Page carries cursor-based pagination state. There is no total: the
        cursor
         walks the result set without ever counting it, and a count would cost a second
         query on every list.
    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.
    OperationMetadata:
      required:
        - id
        - accountId
        - workspaceId
        - profileId
        - createdAt
      type: object
      properties:
        id:
          readOnly: true
          type: string
          description: >-
            Unique identifier for the operation (prefixed ULID, e.g.,
            "obj_01HXK...")
        accountId:
          readOnly: true
          example: account_01HXKD2E5NQM3T9AYWCFTJHJVF
          type: string
          description: >-
            Account this operation belongs to for multi-tenant isolation
            (prefixed ULID)
        workspaceId:
          readOnly: true
          example: workspace_01HXKD2E5NQM3T9AYWCF133E3Q
          type: string
          description: >-
            Workspace this operation belongs to for organizational grouping
            (prefixed ULID)
        labels:
          type: object
          additionalProperties:
            type: string
          description: |-
            Key-value pairs for categorization and filtering. Values are 0-63
             alphanumeric characters with "-", "_", or "." allowed between; keys
             follow the same shape and additionally accept an optional DNS-subdomain
             prefix (e.g. "cadenya.com/") of at most 253 characters.
             Examples: {"priority": "high", "source": "api", "workflow": "onboarding"}
        createdAt:
          readOnly: true
          type: string
          description: |-
            Timestamp when this operation was created
             ULID includes timestamp information, but this explicit field enables easier querying
          format: date-time
        externalId:
          type: string
          description: >-
            External ID for the operation (e.g., a workflow ID from an external
            system)
        profileId:
          readOnly: true
          example: profile_01HXKD2E5NQM3T9AYWCFS0AP08
          type: string
          description: >-
            ID of the actor (user or service account) that created this
            operation
      description: >-
        Metadata for ephemeral operations and activities (e.g., objectives,
        executions, runs)
    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.
    ObjectiveContextWindowInfo:
      type: object
      properties:
        objective:
          $ref: '#/components/schemas/OperationMetadata'
        createdBy:
          $ref: '#/components/schemas/Profile'
    Profile:
      required:
        - metadata
        - spec
      type: object
      properties:
        metadata:
          $ref: '#/components/schemas/AccountResourceMetadata'
        spec:
          $ref: '#/components/schemas/ProfileSpec'
      description: |-
        A profile identifies a user or non-human principal (such as an API key)
         at the account level. Profiles are account-scoped and can be granted access
         to multiple workspaces.
    AccountResourceMetadata:
      required:
        - id
        - accountId
        - name
        - profileId
      type: object
      properties:
        id:
          readOnly: true
          type: string
          description: >-
            Unique identifier for the resource (prefixed ULID, e.g.,
            "apikey_01HXK...")
        accountId:
          readOnly: true
          example: account_01HXKD2E5NQM3T9AYWCFTJHJVF
          type: string
          description: >-
            Account this resource belongs to for multi-tenant isolation
            (prefixed ULID)
        name:
          type: string
          description: >-
            Human-readable name for the resource (e.g., "Customer Support
            Agent", "Email Tool")
             Required for resources that users interact with directly
        externalId:
          type: string
          description: >-
            External ID for the resource (e.g., a workflow ID from an external
            system)
        labels:
          type: object
          additionalProperties:
            type: string
          description: |-
            Key-value pairs for categorization and filtering. Values are 0-63
             alphanumeric characters with "-", "_", or "." allowed between; keys
             follow the same shape and additionally accept an optional DNS-subdomain
             prefix (e.g. "cadenya.com/") of at most 253 characters.
             Examples: {"environment": "production", "team": "platform", "version": "v2"}
        profileId:
          readOnly: true
          example: profile_01HXKD2E5NQM3T9AYWCFS0AP08
          type: string
        createdAt:
          readOnly: true
          type: string
          format: date-time
      description: >-
        AccountResourceMetadata is used to represent a resource that is
        associated to an account but not to a workspace.
    ProfileSpec:
      required:
        - type
      type: object
      properties:
        email:
          type: string
          description: >-
            Email address of the profile. Required and unique within an account
            for
             user profiles.
        name:
          type: string
          description: Display name (e.g., "Bobby Tables").
        type:
          enum:
            - PROFILE_TYPE_UNSPECIFIED
            - PROFILE_TYPE_USER
            - PROFILE_TYPE_API_KEY
            - PROFILE_TYPE_SYSTEM
          type: string
          description: >-
            Whether this profile represents a human user, an API key, or a
            system
             principal.
          format: enum
      description: Configuration for a profile.
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT

````