MicrosoftBackendSKILL.mdVerified source

Agent Skill

Azure Cosmos DB for TypeScript

Implement Cosmos DB document CRUD, queries, partitioning, bulk operations, and container management.

cosmos-dbdatabasetypescript

Skill specification

Declared by Microsoft in the package front matter. Trigger conditions are what the coding agent matches on before it loads the skill.

Azure Cosmos DB for TypeScript SKILL.md front matter fields
Skill nameazure-cosmos-ts
Trigger conditionsAzure Cosmos DB JavaScript/TypeScript SDK (@azure/cosmos) for data plane operations. Use for CRUD operations on documents, queries, bulk operations, and container management. Triggers: "Cosmos DB", "@azure/cosmos", "CosmosClient", "document CRUD", "NoSQL queries", "bulk operations", "partition key", "container.items".
Declared licenseMIT
Version1.0.0
AuthorMicrosoft
Package@azure/cosmos

Install azure-cosmos-ts

Agent Skills are a shared file format, but each client discovers them from a different directory. Copy the command for your agent, then start a new session so the skill is picked up.

Claude Code

.claude/skills/azure-cosmos-ts/SKILL.md

Project skills are committed with the repo. Use the user directory for a personal install across every project.

Project install

mkdir -p .claude/skills/azure-cosmos-ts && curl -fsSL 'https://raw.githubusercontent.com/microsoft/skills/main/.github/plugins/azure-sdk-typescript/skills/azure-cosmos-ts/SKILL.md' -o .claude/skills/azure-cosmos-ts/SKILL.md

Personal install

mkdir -p ~/.claude/skills/azure-cosmos-ts && curl -fsSL 'https://raw.githubusercontent.com/microsoft/skills/main/.github/plugins/azure-sdk-typescript/skills/azure-cosmos-ts/SKILL.md' -o ~/.claude/skills/azure-cosmos-ts/SKILL.md

Codex

.agents/skills/azure-cosmos-ts/SKILL.md

Codex reads `.agents/skills/` as its primary location, which is also the cross-platform default other clients honour.

Project install

mkdir -p .agents/skills/azure-cosmos-ts && curl -fsSL 'https://raw.githubusercontent.com/microsoft/skills/main/.github/plugins/azure-sdk-typescript/skills/azure-cosmos-ts/SKILL.md' -o .agents/skills/azure-cosmos-ts/SKILL.md

Personal install

mkdir -p ~/.agents/skills/azure-cosmos-ts && curl -fsSL 'https://raw.githubusercontent.com/microsoft/skills/main/.github/plugins/azure-sdk-typescript/skills/azure-cosmos-ts/SKILL.md' -o ~/.agents/skills/azure-cosmos-ts/SKILL.md

Cursor

.cursor/skills/azure-cosmos-ts/SKILL.md

Cursor also loads `.agents/skills/`, `.claude/skills/`, and `.codex/skills/`, so one committed copy can serve several clients.

Project install

mkdir -p .cursor/skills/azure-cosmos-ts && curl -fsSL 'https://raw.githubusercontent.com/microsoft/skills/main/.github/plugins/azure-sdk-typescript/skills/azure-cosmos-ts/SKILL.md' -o .cursor/skills/azure-cosmos-ts/SKILL.md

Personal install

mkdir -p ~/.cursor/skills/azure-cosmos-ts && curl -fsSL 'https://raw.githubusercontent.com/microsoft/skills/main/.github/plugins/azure-sdk-typescript/skills/azure-cosmos-ts/SKILL.md' -o ~/.cursor/skills/azure-cosmos-ts/SKILL.md

Gemini CLI

.gemini/skills/azure-cosmos-ts/SKILL.md

Gemini CLI reads `.agents/skills/` first when both directories exist.

Project install

mkdir -p .gemini/skills/azure-cosmos-ts && curl -fsSL 'https://raw.githubusercontent.com/microsoft/skills/main/.github/plugins/azure-sdk-typescript/skills/azure-cosmos-ts/SKILL.md' -o .gemini/skills/azure-cosmos-ts/SKILL.md

Personal install

mkdir -p ~/.gemini/skills/azure-cosmos-ts && curl -fsSL 'https://raw.githubusercontent.com/microsoft/skills/main/.github/plugins/azure-sdk-typescript/skills/azure-cosmos-ts/SKILL.md' -o ~/.gemini/skills/azure-cosmos-ts/SKILL.md

GitHub Copilot

.github/skills/azure-cosmos-ts/SKILL.md

Copilot in VS Code discovers repository skills from `.github/skills/`.

Project install

mkdir -p .github/skills/azure-cosmos-ts && curl -fsSL 'https://raw.githubusercontent.com/microsoft/skills/main/.github/plugins/azure-sdk-typescript/skills/azure-cosmos-ts/SKILL.md' -o .github/skills/azure-cosmos-ts/SKILL.md

Personal install

mkdir -p ~/.copilot/skills/azure-cosmos-ts && curl -fsSL 'https://raw.githubusercontent.com/microsoft/skills/main/.github/plugins/azure-sdk-typescript/skills/azure-cosmos-ts/SKILL.md' -o ~/.copilot/skills/azure-cosmos-ts/SKILL.md

Published by Microsoft under MIT. Rendered from the package in github.com/microsoft/skills/tree/main/.github/plugins/azure-sdk-typescript/skills/azure-cosmos-ts.

@azure/cosmos (TypeScript/JavaScript)

Data plane SDK for Azure Cosmos DB NoSQL API operations — CRUD on documents, queries, bulk operations.

⚠️ Data vs Management Plane - This SDK (@azure/cosmos): CRUD operations on documents, queries, stored procedures - Management SDK (@azure/arm-cosmosdb): Create accounts, databases, containers via ARM

Installation

npm install @azure/cosmos @azure/identity

Current Version: 4.9.0 Node.js: >= 20.0.0

Environment Variables

COSMOS_ENDPOINT=https://<account>.documents.azure.com:443/
COSMOS_DATABASE=<database-name>
COSMOS_CONTAINER=<container-name>
# For key-based auth only (prefer AAD)
COSMOS_KEY=<account-key>
AZURE_TOKEN_CREDENTIALS=prod # Required only if DefaultAzureCredential is used in production

Authentication

Microsoft Entra Token Credential (Recommended)

import { CosmosClient } from "@azure/cosmos";
import { DefaultAzureCredential, ManagedIdentityCredential } from "@azure/identity";

// Local dev: DefaultAzureCredential. Production: set AZURE_TOKEN_CREDENTIALS=prod or AZURE_TOKEN_CREDENTIALS=<specific_credential>
const credential = new DefaultAzureCredential({requiredEnvVars: ["AZURE_TOKEN_CREDENTIALS"]});
// Or use a specific credential directly in production:
// See https://learn.microsoft.com/javascript/api/overview/azure/identity-readme?view=azure-node-latest#credential-classes
// const credential = new ManagedIdentityCredential();

const client = new CosmosClient({
  endpoint: process.env.COSMOS_ENDPOINT!,
  aadCredentials: credential,
});

Key-Based Authentication

import { CosmosClient } from "@azure/cosmos";

// Option 1: Endpoint + Key
const client = new CosmosClient({
  endpoint: process.env.COSMOS_ENDPOINT!,
  key: process.env.COSMOS_KEY!,
});

// Option 2: Connection String
const client = new CosmosClient(process.env.COSMOS_CONNECTION_STRING!);

Resource Hierarchy

CosmosClient
└── Database
    └── Container
        ├── Items (documents)
        ├── Scripts (stored procedures, triggers, UDFs)
        └── Conflicts

Core Operations

Database & Container Setup

const { database } = await client.databases.createIfNotExists({
  id: "my-database",
});

const { container } = await database.containers.createIfNotExists({
  id: "my-container",
  partitionKey: { paths: ["/partitionKey"] },
});

Create Document

interface Product {
  id: string;
  partitionKey: string;
  name: string;
  price: number;
}

const item: Product = {
  id: "product-1",
  partitionKey: "electronics",
  name: "Laptop",
  price: 999.99,
};

const { resource } = await container.items.create<Product>(item);

Read Document

const { resource } = await container
  .item("product-1", "electronics") // id, partitionKey
  .read<Product>();

if (resource) {
  console.log(resource.name);
}

Update Document (Replace)

const { resource: existing } = await container
  .item("product-1", "electronics")
  .read<Product>();

if (existing) {
  existing.price = 899.99;
  const { resource: updated } = await container
    .item("product-1", "electronics")
    .replace<Product>(existing);
}

Upsert Document

const item: Product = {
  id: "product-1",
  partitionKey: "electronics",
  name: "Laptop Pro",
  price: 1299.99,
};

const { resource } = await container.items.upsert<Product>(item);

Delete Document

await container.item("product-1", "electronics").delete();

Patch Document (Partial Update)

import { PatchOperation } from "@azure/cosmos";

const operations: PatchOperation[] = [
  { op: "replace", path: "/price", value: 799.99 },
  { op: "add", path: "/discount", value: true },
  { op: "remove", path: "/oldField" },
];

const { resource } = await container
  .item("product-1", "electronics")
  .patch<Product>(operations);

Queries

Simple Query

const { resources } = await container.items
  .query<Product>("SELECT * FROM c WHERE c.price < 1000")
  .fetchAll();

Parameterized Query (Recommended)

import { SqlQuerySpec } from "@azure/cosmos";

const querySpec: SqlQuerySpec = {
  query: "SELECT * FROM c WHERE c.partitionKey = @category AND c.price < @maxPrice",
  parameters: [
    { name: "@category", value: "electronics" },
    { name: "@maxPrice", value: 1000 },
  ],
};

const { resources } = await container.items
  .query<Product>(querySpec)
  .fetchAll();

Query with Pagination

const queryIterator = container.items.query<Product>(querySpec, {
  maxItemCount: 10, // Items per page
});

while (queryIterator.hasMoreResults()) {
  const { resources, continuationToken } = await queryIterator.fetchNext();
  console.log(`Page with ${resources?.length} items`);
  // Use continuationToken for next page if needed
}

Cross-Partition Query

const { resources } = await container.items
  .query<Product>(
    "SELECT * FROM c WHERE c.price > 500",
    { enableCrossPartitionQuery: true }
  )
  .fetchAll();

Bulk Operations

Execute Bulk Operations

import { BulkOperationType, OperationInput } from "@azure/cosmos";

const operations: OperationInput[] = [
  {
    operationType: BulkOperationType.Create,
    resourceBody: { id: "1", partitionKey: "cat-a", name: "Item 1" },
  },
  {
    operationType: BulkOperationType.Upsert,
    resourceBody: { id: "2", partitionKey: "cat-a", name: "Item 2" },
  },
  {
    operationType: BulkOperationType.Read,
    id: "3",
    partitionKey: "cat-b",
  },
  {
    operationType: BulkOperationType.Replace,
    id: "4",
    partitionKey: "cat-b",
    resourceBody: { id: "4", partitionKey: "cat-b", name: "Updated" },
  },
  {
    operationType: BulkOperationType.Delete,
    id: "5",
    partitionKey: "cat-c",
  },
  {
    operationType: BulkOperationType.Patch,
    id: "6",
    partitionKey: "cat-c",
    resourceBody: {
      operations: [{ op: "replace", path: "/name", value: "Patched" }],
    },
  },
];

const response = await container.items.executeBulkOperations(operations);

response.forEach((result, index) => {
  if (result.statusCode >= 200 && result.statusCode < 300) {
    console.log(`Operation ${index} succeeded`);
  } else {
    console.error(`Operation ${index} failed: ${result.statusCode}`);
  }
});

Partition Keys

Simple Partition Key

const { container } = await database.containers.createIfNotExists({
  id: "products",
  partitionKey: { paths: ["/category"] },
});

Hierarchical Partition Key (MultiHash)

import { PartitionKeyDefinitionVersion, PartitionKeyKind } from "@azure/cosmos";

const { container } = await database.containers.createIfNotExists({
  id: "orders",
  partitionKey: {
    paths: ["/tenantId", "/userId", "/sessionId"],
    version: PartitionKeyDefinitionVersion.V2,
    kind: PartitionKeyKind.MultiHash,
  },
});

// Operations require array of partition key values
const { resource } = await container.items.create({
  id: "order-1",
  tenantId: "tenant-a",
  userId: "user-123",
  sessionId: "session-xyz",
  total: 99.99,
});

// Read with hierarchical partition key
const { resource: order } = await container
  .item("order-1", ["tenant-a", "user-123", "session-xyz"])
  .read();

Error Handling

import { ErrorResponse } from "@azure/cosmos";

try {
  const { resource } = await container.item("missing", "pk").read();
} catch (error) {
  if (error instanceof ErrorResponse) {
    switch (error.code) {
      case 404:
        console.log("Document not found");
        break;
      case 409:
        console.log("Conflict - document already exists");
        break;
      case 412:
        console.log("Precondition failed (ETag mismatch)");
        break;
      case 429:
        console.log("Rate limited - retry after:", error.retryAfterInMs);
        break;
      default:
        console.error(`Cosmos error ${error.code}: ${error.message}`);
    }
  }
  throw error;
}

Optimistic Concurrency (ETags)

// Read with ETag
const { resource, etag } = await container
  .item("product-1", "electronics")
  .read<Product>();

if (resource && etag) {
  resource.price = 899.99;
  
  try {
    // Replace only if ETag matches
    await container.item("product-1", "electronics").replace(resource, {
      accessCondition: { type: "IfMatch", condition: etag },
    });
  } catch (error) {
    if (error instanceof ErrorResponse && error.code === 412) {
      console.log("Document was modified by another process");
    }
  }
}

TypeScript Types Reference

import {
  // Client & Resources
  CosmosClient,
  Database,
  Container,
  Item,
  Items,
  
  // Operations
  OperationInput,
  BulkOperationType,
  PatchOperation,
  
  // Queries
  SqlQuerySpec,
  SqlParameter,
  FeedOptions,
  
  // Partition Keys
  PartitionKeyDefinition,
  PartitionKeyDefinitionVersion,
  PartitionKeyKind,
  
  // Responses
  ItemResponse,
  FeedResponse,
  ResourceResponse,
  
  // Errors
  ErrorResponse,
} from "@azure/cosmos";

Best Practices

  1. Use Microsoft Entra Token Credential — Use DefaultAzureCredential for local development; use ManagedIdentityCredential or WorkloadIdentityCredential for production
  2. Always use parameterized queries — Prevents injection, improves plan caching
  3. Specify partition key — Avoid cross-partition queries when possible
  4. Use bulk operations — For multiple writes, use executeBulkOperations
  5. Handle 429 errors — Implement retry logic with exponential backoff
  6. Use ETags for concurrency — Prevent lost updates in concurrent scenarios
  7. Close client on shutdown — Call client.dispose() in cleanup

Common Patterns

Service Layer Pattern

export class ProductService {
  private container: Container;

  constructor(client: CosmosClient) {
    this.container = client
      .database(process.env.COSMOS_DATABASE!)
      .container(process.env.COSMOS_CONTAINER!);
  }

  async getById(id: string, category: string): Promise<Product | null> {
    try {
      const { resource } = await this.container
        .item(id, category)
        .read<Product>();
      return resource ?? null;
    } catch (error) {
      if (error instanceof ErrorResponse && error.code === 404) {
        return null;
      }
      throw error;
    }
  }

  async create(product: Omit<Product, "id">): Promise<Product> {
    const item = { ...product, id: crypto.randomUUID() };
    const { resource } = await this.container.items.create<Product>(item);
    return resource!;
  }

  async findByCategory(category: string): Promise<Product[]> {
    const querySpec: SqlQuerySpec = {
      query: "SELECT * FROM c WHERE c.partitionKey = @category",
      parameters: [{ name: "@category", value: category }],
    };
    const { resources } = await this.container.items
      .query<Product>(querySpec)
      .fetchAll();
    return resources;
  }
}

Related SDKs

SDKPurposeInstall
@azure/cosmosData plane (this SDK)npm install @azure/cosmos
@azure/arm-cosmosdbManagement plane (ARM)npm install @azure/arm-cosmosdb
@azure/identityAuthenticationnpm install @azure/identity

Add the registry badge

Maintainers can link this listing from the skill's own README. Free, no account needed, and it points back at the rendered package for anyone browsing the repo.

Markdown

[![Azure Cosmos DB for TypeScript on tokens&](https://tokensand.com/api/badges/skill/microsoft-azure-cosmos-ts)](https://tokensand.com/agent-skills/microsoft-azure-cosmos-ts)

HTML

<a href="https://tokensand.com/agent-skills/microsoft-azure-cosmos-ts" target="_blank" rel="noopener">
  <img src="https://tokensand.com/api/badges/skill/microsoft-azure-cosmos-ts" alt="Azure Cosmos DB for TypeScript on tokens&" />
</a>

More Microsoft Agent Skills

All Agent Skills