Cortex Agent SDK reference

Use this reference when you need details about SDK response objects, thread message helpers, transport wrappers, error classes, retry behavior, and per-request options. For workflow examples, see Conversations and Use the direct Cortex Agent API. For authentication examples, see Authenticate Cortex Agent SDK requests.

Response views

Response views wrap the typed message content union so you can use getters such as text, tool_uses or toolUses, tables, and charts without switching on content discriminators yourself.

ClassWraps
AgentResponseViewAn assistant response from a direct run.
AgentResponseThe high-level response returned by a conversation Turn.
ThreadMessageViewA persisted thread message returned by the direct threads resource.

Content getters

Each getter filters the content array down to one kind of item.

Common members include:

  • view.text: all text values concatenated in order
  • view.content: full content array
  • view.texts: text blocks
  • view.thinkings: reasoning blocks
  • view.toolUses: tool calls made by the model
  • view.toolResults: tool results
  • view.toolResultsAggregated: aggregated tool-result rollups
  • view.tables: tabular results
  • view.charts: chart artifacts
  • view.assets: asset references
  • view.suggestedQueries: suggested follow-up queries
  • view.images: inline images
  • view.documents: document references
  • view.artifacts: persisted artifacts
  • view.permissionDecisions: permission decisions emitted by the agent
  • view.actualUserMessages: user-facing messages emitted by the agent

Finder methods

Search response content by tool name.

import type { ToolResultContentItem, ToolUseContentItem } from "@snowflake/cortex-agent-sdk/types";

const anyCall: ToolUseContentItem | undefined = view.findToolUse();
const analystCall: ToolUseContentItem | undefined = view.findToolUse("analyst");
const sqlResult: ToolResultContentItem | undefined = view.findToolResult("system_execute_sql");
const allSqlCalls: ToolUseContentItem[] = view.getToolUsesByName("system_execute_sql");

The single-item finders return undefined when nothing matches.

AgentResponseView

AgentResponseView represents a completed assistant response from the direct API.

Important members include:

  • view.role: "assistant", always
  • view.metadata: ResponseMetadata, including run_id, thread_id, message IDs, and usage
  • view.events: ServerSentEvent[] | undefined, populated when the view was built from a stream
  • view.requestId: Snowflake request ID, when present
  • view.responseBody: full parsed response body
  • view.response: underlying HTTP response, available for headers and status only

You can create an AgentResponseView by calling a direct run method with stream: false, by calling AgentResponseView.fromStream(stream) after draining an AgentRunStream, or by calling AgentResponseView.fromThreadMessage(message) when reading a persisted assistant reply from thread history.

ThreadMessageView

ThreadMessageView wraps a raw thread message returned by the direct threads resource.

import {
  ThreadMessageView,
  type APIResponse,
  type DescribeThreadsResponse,
  type ThreadMessage,
} from "@snowflake/cortex-agent-sdk/api";

const detail: APIResponse<DescribeThreadsResponse> = await api.threads.describe(threadId);
for (const raw of detail.responseBody.messages ?? []) {
  const message: ThreadMessageView = new ThreadMessageView(raw as ThreadMessage);
  console.log(message.messageId, message.role, message.text);
}

Thread-specific members include messageId, parentId, role, createdOn, requestId, messageType, status, schemaVersion, tags, and raw.

Snowflake thread and message identifiers are preserved as strings so int64 IDs remain exact.

Thread pagination

Use pagination helpers when listing threads through the direct API.

api.threads.list() returns a response wrapper whose .page field is a ThreadsPage.

import type { PagedAPIResponse, ThreadMetadata, ThreadsPage } from "@snowflake/cortex-agent-sdk/api";

const first: PagedAPIResponse<ThreadMetadata> = await api.threads.list({ page_size: 50 });
const page: ThreadsPage<ThreadMetadata> = first.page;

for await (const thread of page) {
  console.log(thread.thread_id, thread.thread_name);
}

You can also page manually:

let current: ThreadsPage<ThreadMetadata> = (
  await api.threads.list({ page_size: 100 })
).page;
while (true) {
  for (const thread of current.data) {
    console.log(thread.thread_id);
  }
  if (!current.hasMore) break;
  current = (await current.getNextPage()).page;
}

Transport wrappers

Direct API resource methods can expose parsed response bodies together with transport metadata. Use these wrappers when you need request IDs, response headers, or status details from the underlying HTTP call.

APIResponse<T>

APIResponse<T> is returned by methods such as api.threads.create(), api.agent.create(), and api.requestWithResponse():

import type { APIResponse } from "@snowflake/cortex-agent-sdk/api";
import type { AgentResponse as AgentResponseBody } from "@snowflake/cortex-agent-sdk/types";

const res: APIResponse<AgentResponseBody> = await api.requestWithResponse<AgentResponseBody>(
  "/api/v2/cortex/agent:run",
  { method: "POST", body: { ...body, stream: false } },
);

res.responseBody;
res.requestId;
res.response.headers.get("x-snowflake-request-id");

Use these members:

  • responseBody: parsed JSON body
  • response: raw HTTP Response
  • requestId: x-snowflake-request-id, when present

The body has already been consumed to populate responseBody. Do not call res.response.json() or res.response.text().

ResponseCarrier<T>

ResponseCarrier<T> is not a class that application code usually constructs directly. It is the shared TypeScript base behind raw wrapper objects such as AsyncRun and AgentResponseView, which is why those objects expose the same transport fields as APIResponse<T>: responseBody, response, and requestId.

The following example reads the fields that those wrappers inherit from ResponseCarrier<T>:

import type { AgentResponseView, AsyncRun } from "@snowflake/cortex-agent-sdk/api";

const view: AgentResponseView = await api.agent.run({
  messages: [{ role: "user", content: [{ type: "text", text: "Hello." }] }],
  stream: false,
});

const run: AsyncRun = await api.agent.run({
  messages: [{ role: "user", content: [{ type: "text", text: "Long task." }] }],
  stream: false,
  background: true,
});

console.log(view.responseBody, view.requestId);
console.log(run.responseBody, run.requestId);

api.requestWithResponse

Use requestWithResponse() when you need the TypeScript direct API client’s request primitive and the APIResponse<T> transport wrapper.

import type { APIResponse } from "@snowflake/cortex-agent-sdk/api";
import type { AgentResponse as AgentResponseBody } from "@snowflake/cortex-agent-sdk/types";

const res: APIResponse<AgentResponseBody> = await api.requestWithResponse<AgentResponseBody>(
  "/api/v2/cortex/agent:run",
  { method: "POST", body: { ...body, stream: false } },
);

It rejects stream: true. For streaming requests, use api.agent.stream(), api.agent.run(), api.runs.stream(), or api.runs.resume().

Error hierarchy

The SDK raises typed errors for API and client-side failures.

Error
└── CortexAgentError
    └── CortexAgentAPIError
        ├── BadRequestError
        ├── AuthenticationError
        ├── PermissionDeniedError
        ├── NotFoundError
        ├── ConflictError
        ├── UnprocessableEntityError
        ├── RateLimitError
        └── InternalServerError

Every CortexAgentError can expose name, status, requestId, and body.

import {
  CortexAgentAPIError,
  CortexAgentError,
  NotFoundError,
  RateLimitError,
} from "@snowflake/cortex-agent-sdk";

try {
  await api.threads.describe(threadId);
} catch (error) {
  if (error instanceof RateLimitError) {
    // 429
  } else if (error instanceof NotFoundError) {
    // 404
  } else if (error instanceof CortexAgentAPIError) {
    // other non-2xx HTTP responses
  } else if (error instanceof CortexAgentError) {
    // client-side failures such as validation or SSE parsing
  } else {
    throw error;
  }
}

If an auth-refresh callback fails, the SDK raises the original API error and attaches safe refresh metadata. In TypeScript, read err.authRefresh.provider, err.authRefresh.attempt, err.authRefresh.requestId, and err.cause. In Python, read err.auth_refresh.provider, err.auth_refresh.attempt, err.auth_refresh.request_id, and err.__cause__.

Retries

The SDK can retry transient transport failures:

  • 408
  • 409
  • 429
  • 5xx

Client-level retry defaults apply automatically only to retry-safe methods: GET, HEAD, and OPTIONS. For mutating requests, including agent runs and resource creation, pass a per-request retry policy to opt in to replaying the request after a transient failure.

TypeScript retries use exponential backoff with Retry-After support and these defaults:

  • Initial delay: 500ms
  • Multiplier: 2x
  • Maximum nominal delay: 30_000ms
  • Additive jitter: up to 500ms
  • Default maxRetries: 2
  • Default retryStreaming: false

Configure retries on the client for retry-safe methods:

new CortexAgentClient({
  account,
  auth,
  retryPolicy: { maxRetries: 5 },
});

Or per request:

await api.threads.describe(
  threadId,
  {},
  { retryPolicy: { maxRetries: 0 } },
);

Mutating requests require a per-request retry policy:

await api.agent.run(
  {
    messages: [{ role: "user", content: [{ type: "text", text: "Summarize the thread." }] }],
    stream: false,
  },
  { retryPolicy: { maxRetries: 1 } },
);

Streaming requests are not retried by default, including pre-response network failures. Opt in explicitly when reconnecting to a run stream:

const stream = api.runs.resume(runId, {
  retryPolicy: { maxRetries: 1, retryStreaming: true },
});
await stream.done();

Mid-stream retry remains a caller concern.

Request options

Raw resource request methods accept per-request options.

The TypeScript RequestOpts type includes:

export interface RequestOpts {
  signal?: AbortSignal;
  timeout?: number;
  retryPolicy?: RetryPolicy;
  headers?: Record<string, string>;
  query?: Record<string, string | number | boolean | undefined>;
  streamReadTimeoutMs?: number;
}

Use these fields for:

  • signal: abort a request
  • timeout: non-streaming request timeout in milliseconds
  • retryPolicy: per-request retry override
  • headers: custom headers merged into the request
  • query: extra query parameters
  • streamReadTimeoutMs: dead-socket timeout for streaming requests

On methods that also take query parameters, opts is the last argument:

await api.threads.describe(threadId, {}, { retryPolicy: { maxRetries: 0 } }); // correct
await api.threads.describe(threadId, { retryPolicy: { maxRetries: 0 } }); // wrong: becomes a query param

Where your configuration of Cortex Code uses a model provided on the Model and Service Pass-Through Terms, your use of that model is further subject to the terms for that model on that page.

The data classification of inputs and outputs are as set forth in the following table.

Input data classificationOutput data classificationDesignation
Usage DataCustomer Data

Covered AI Features

[1]

For additional information, refer to Snowflake AI and ML.