Node SDK

Use the official Node SDK when your agent runtime already runs in Node.js or TypeScript.

Install

npm install @r4-sdk/sdk

Requires Node.js 18 or newer.

Quick Start

import R4 from '@r4-sdk/sdk'
 
const r4 = await R4.create({
  apiKey: process.env.R4_API_KEY!,
  privateKeyPath: './agent-private-key.pem',
})
 
console.log(r4.env.GITHUB_PRODUCTION_TOKEN)

Required Configuration

OptionRequiredDescription
apiKeyYesAGENT API key in {accessKey}.{secret} format
privateKeyNoPEM-encoded RSA private key kept locally by the runtime
privateKeyPathNoPath to the PEM-encoded RSA private key
projectIdNoOptional project filter
trustStorePathNoOptional path to the local trust-store JSON
baseUrlNoAPI base URL, defaults to https://r4.dev

Provide either privateKey or privateKeyPath.

Create the agent first, then let the runtime complete this setup before operators add the agent to security groups, projects, or direct vault shares. The first public-key registration is what makes wrapped vault keys possible for that runtime.

What R4.create() Does

R4.create() is the canonical runtime entry point.

It:

  1. authenticates with the AGENT API key
  2. derives the public key from the local private key
  3. registers that public key with POST /api/v1/machine/vault/public-key
  4. becomes eligible for vault-backed access grants after that first registration
  5. lists accessible vaults
  6. verifies signer directories, transparency proofs, and checkpoint metadata
  7. unwraps vault DEKs locally
  8. decrypts field ciphertext locally into a flat environment map

If R4.create() fails because no wrapped key exists for a vault, check the onboarding order first: the runtime key must be registered before the operator grants the access path that leads to that vault.

Access the Decrypted Environment Map

const r4 = await R4.create({
  apiKey: process.env.R4_API_KEY!,
  privateKeyPath: './agent-private-key.pem',
})
 
const dbPassword = r4.env.PRIMARY_DATABASE_PASSWORD

Refresh Secrets

Use refresh() when the runtime is long-lived and needs the latest shared values:

await r4.refresh()

When to Use the SDK

Choose the SDK when the runtime:

  • already runs in Node.js
  • wants direct in-process secret access
  • needs programmatic refresh logic
  • wants the zero-trust workflow without shelling out to the CLI

Choose the CLI when shell commands and scripts are the main integration surface.

Low-Level Machine Routes

If you need a machine endpoint that does not have a dedicated SDK helper yet, use the low-level bridge:

const result = await r4.requestMachine({
  method: 'GET',
  path: '/webhook',
})

You can also use new R4Client(apiKey, baseUrl).requestMachine(...) when you want authenticated machine access without booting the full zero-trust decrypt flow.

If the SDK is missing a capability you need and the current CLI, MCP server, or raw machine API also does not cover it, submit product-gap feedback through POST /api/v1/machine/feedback with an AGENT API key. Do not include secrets or private user data in that payload.

Managed Token Providers

The SDK now also supports budget-aware token-provider helpers without giving R4 the plaintext vendor secret.

Read decrypted provider fields locally

const provider = await r4.getTokenProviderFields('TOKEN_PROVIDER_ID', {
  unsafeExport: true,
})
 
console.log(provider.providerType)
console.log(provider.fields['API Key'])

Call Anthropic through a managed token provider

const result = await r4.callAnthropicWithTokenProvider({
  tokenProviderId: 'TOKEN_PROVIDER_ID',
  body: {
    model: 'claude-sonnet-4-5-20250929',
    max_tokens: 1024,
    messages: [{ role: 'user', content: 'Summarize the latest runbook changes.' }],
  },
})
 
console.log(result.response)
console.log(result.usage.actualCostUsd)

That path:

  1. fetches the provider-scoped runtime bundle from R4
  2. decrypts the provider secret locally
  3. checks the estimated worst-case hard-block budget state with R4
  4. sends the Anthropic request directly from the runtime
  5. reports finalized usage back to R4