npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@cxpa/sdk

v0.7.0

Published

Official SDK for the CXP Agent Platform

Readme

@cxpa/sdk

Official SDK for the CXP Agent Platform.

Two consumer roles, two subpath imports:

| Subpath | For | What it gives you | |---|---|---| | @cxpa/sdk/agent | Agent runtime code (Trigger.dev tasks, n8n workflows, standalone Node) | createAgentClient, triggerRun, registerRun, ingestRun | | @cxpa/sdk/zone | Next.js zone apps embedded in a platform agent page | createZoneClient, createZoneMiddleware, getSession | | @cxpa/sdk/types | Shared types (errors, payload shapes) | Run, RunStatus, CallbackPayload, ResolvedCredential, ApiError |

Install

npm install @cxpa/sdk

next is an optional peer dependency — install it only if you use @cxpa/sdk/zone.

Agent runtime — quickstart

import { createAgentClient } from '@cxpa/sdk/agent'

const cxpa = createAgentClient({
  baseUrl: process.env.CXPA_API_URL!,
  apiKey:  process.env.CXPA_API_KEY!,
  runId:   payload.runId,
  credentialsToken: payload.credentialsToken,
})

await cxpa.started()
const cred = await cxpa.resolveCredential(payload.connectionIds.openai.connectionId)
await cxpa.complete({ output: { result: 'done' } })

Human-in-the-loop

Pause a run for review with cxpa.waiting({ tokenId, description, url? }) — pass an optional absolute http(s) url to override the {{run_url}} link in waiting-state notifications so reviewers land on your own HITL UI — then resume it — from anywhere holding the agent_api_key (an approval service, a Slack backend, the task itself) — with cxpa.completeWaitpoint(payload?). The waitpoint token is resolved server-side from the run, so only the bound runId is needed. Zone apps resume via createZoneClient().runs.completeWaitpoint(runId, payload?) instead.

Ingest-key operations

For agent-scoped operations using ingest_api_key (not agent_api_key):

import {
  triggerRun,
  triggerRunAndWait,
  registerRun,
  ingestRun,
} from '@cxpa/sdk/agent'

// Start a platform-managed run (fire-and-forget — returns immediately)
await triggerRun({ baseUrl, ingestApiKey, agentId, input: {...} })

// Synchronous trigger — block until the run finishes, then return its output.
// Designed for agents that produce a payload the caller consumes inline,
// e.g. PDF reports, generated documents, AI-rendered responses.
const result = await triggerRunAndWait({
  baseUrl, ingestApiKey, agentId,
  input:     { topic: 'Q3 financial summary' },
  timeoutMs: 120_000,   // server further caps at agents.running_timeout_ms
})

if (result.timedOut) {
  // Wait window elapsed; the run is still in flight. Poll for completion.
  console.log('still running:', result.runId)
} else if (result.status === 'completed') {
  // result.output_data has the agent payload.
  return new Response(result.output_data?.pdf as string, {
    headers: { 'content-type': 'application/pdf' },
  })
} else {
  throw new Error(`Run ${result.status}: ${result.error}`)
}

// Register an externally-triggered run, get a credentialsToken
const { runId, credentialsToken } = await registerRun({
  baseUrl, ingestApiKey, agentId, externalRunId: '...', input: {...}
})

// Monitoring-only status update
await ingestRun({
  baseUrl, ingestApiKey, agentId,
  externalRunId: '...', status: 'completed',
  startedAt: '...', completedAt: '...', durationMs: 1234,
})

When to use triggerRunAndWait vs triggerRun

| Use triggerRun when | Use triggerRunAndWait when | |---|---| | The caller does not need the agent output in the response | The caller hands the output straight to the end user (download, render, forward) | | The run takes longer than ~5 minutes | The run completes in seconds or low minutes | | You'll poll, subscribe, or wait for a callback yourself | You want a single HTTP request that returns the result |

Both endpoints take the same input. triggerRunAndWait is supported by every platform-managed runtime — n8n workflows that terminate in a "Respond to Webhook" node return the output inline; Trigger.dev tasks run normally and the platform polls until they reach a terminal state.

Zone app — quickstart

// middleware.ts
import { createZoneMiddleware } from '@cxpa/sdk/zone'

export const middleware = createZoneMiddleware({
  secret: process.env.ZONE_JWT_SECRET!,
  audience: process.env.AUDIENCE_ID!,
})

export const config = {
  matcher: ['/:orgSlug/:agentSlug/app/:path*', '/:orgSlug/:agentSlug/app'],
}
// app/page.tsx
import { getSession, createZoneClient } from '@cxpa/sdk/zone'

export default async function Page() {
  const session = await getSession()
  const cxpa = createZoneClient({
    baseUrl: process.env.PLATFORM_API_BASE_URL!,
    token:   session.token,
    agentId: session.claims.agentId,
  })

  const { runId } = await cxpa.runs.create({ payload: { url: 'https://example.com' } })
  const run = await cxpa.runs.get(runId)
  return <pre>{JSON.stringify(run, null, 2)}</pre>
}

For zone apps that download or render the agent output inline (e.g. a "Generate Report" button that hands the user a PDF), use the synchronous variant — it waits for the run to finish and returns the output in the same response:

const result = await cxpa.runs.createAndWait({
  payload:   { topic: 'Q3 financial summary' },
  timeoutMs: 120_000,
})

if (result.timedOut) {
  // Run is still in flight — fall back to polling cxpa.runs.get(result.runId).
} else if (result.status === 'completed') {
  // result.output_data has whatever the agent returned.
}

Errors

All non-2xx responses throw ApiError:

import { ApiError } from '@cxpa/sdk'

try {
  await cxpa.complete({ output: {} })
} catch (err) {
  if (err instanceof ApiError && err.status === 401) {
    // re-auth
  }
  throw err
}

License

MIT