Node.js vault runtime with a Sovereign Vault architecture: authority is rooted in a master password, and agent identities are fully managed within the vault's encrypted storage.
Source: https://github.com/TheAICompany/cbio-node-runtime
- No CLI / No TUI: Pure library for integration into Node.js applications.
- Authority-centric: Administrative control is tied to the vault's master password, not an external identity.
- Managed Agent Custody: Generate and store agent private keys securely inside the vault.
- Agent Session Tokens: Issue revocable, short-lived (or long-lived) tokens for agents to avoid handling raw private keys.
- Process Isolation: Hard separation between the Security Process (Master) and Agent Processes (Consumers).
- Zero-Leak Discovery: Vault metadata is fully encrypted and hidden until unlocked.
Requires Node >= 18.
npm install @the-ai-company/cbio-node-runtimeThe Sovereign Vault requires only a storage provider and a master password.
import {
createVault,
FsStorageProvider,
createWorkspaceStorage
} from '@the-ai-company/cbio-node-runtime';
const storage = new FsStorageProvider('./my-vaults');
const myVault = await createVault(storage, {
vaultId: 'main-vault',
password: 'your-secure-password',
nickname: 'Production Vault'
});
console.log(`Vault created: ${myVault.nickname}`);import { recoverVault, FsStorageProvider } from '@the-ai-company/cbio-node-runtime';
const vault = await recoverVault(storage, {
vaultId: 'main-vault',
password: 'your-secure-password'
});You can generate and register agents directly within the vault. The vault holds the private keys for full custody.
import { createVaultClient } from '@the-ai-company/cbio-node-runtime';
const client = createVaultClient({ vault: vault.vault });
// Generate and register a new agent in one step
const createdAgent = await client.ownerCreateAgent({
agentId: 'worker-1',
nickname: 'Background Worker'
});
console.log(`Agent public key: ${createdAgent.agent.publicKey}`);
const session = createdAgent.sessionToken;
// RECOMENDED (v1.48.4+): Batch issue tokens for all agents at once
const tokens = await client.ownerIssueAllSessionTokens();// Write a secret and bind it to a target site
const record = await client.ownerWriteSecret({
alias: 'api-token',
plaintext: 'super-secret-value',
targetBindings: [{
kind: 'site',
targetId: 'my-api',
targetUrl: 'https://api.example.com/endpoint',
methods: ['POST']
}]
});
// 4. Grant agent capabilities
await client.ownerGrantCapability({
agentId: 'worker-1',
secretAliases: ['api-token'],
scope: 'https://api.example.com/*',
methods: ['POST']
});
// 5. Setup client with automatic warmup (v1.48.4+)
const client = createVaultClient({
vault,
ownerIdentity: { identityId: 'owner-1' }
// warmup: true is now DEFAULT (v1.48.4+)
// skipWarmup: true // Optional: pass this to disable automatic token generation
});Agents run in isolated processes and communicate with the vault via a transport. Agent execution now requires a Session Token issued by the owner.
import { createAgentClient } from '@the-ai-company/cbio-node-runtime';
const agent = createAgentClient({
agentIdentity: { agentId: 'worker-1' },
capability: myCapability,
token: session.token,
vault: vault.vault
});
const result = await agent.agentDispatch({ ... });The agent process does not execute directly with its raw private key. If it has an identity key, it still needs to exchange that trust for a session token before dispatching.
If an LLM or orchestration layer already knows it needs a broader scope, it can ask for that scope up front instead of triggering one pending dispatch per concrete URL.
const request = await client.ownerSubmitCapabilityRequest({
requester: { kind: 'trusted_executor', id: 'llm-planner' },
agentId: 'worker-1',
secretAliases: ['api-token'],
scope: 'https://api.example.com/users/*',
methods: ['GET'],
justification: 'Need collection-level user read access'
});
const pendingRequests = await client.ownerListPendingCapabilityRequests();
const capability = await client.ownerApproveCapabilityRequest({
requestId: pendingRequests[0].requestId,
capabilityId: 'cap-users-read'
});This flow is separate from dispatch discovery:
ownerSubmitCapabilityRequest(...)creates a pending capability request for owner review.ownerOnPendingCapabilityRequest(...)pushes new requests to the owner UI or controller.ownerApproveCapabilityRequest(...)turns the request into a real stored capability.ownerRejectCapabilityRequest(...)drops the request without granting access.
- Custody Model - Understanding managed agency and key storage.
- Process Isolation - Guidelines for A/B architecture.
- Secret Isolation: Plane-text secrets never leave the Security Process.
- Authority Root: The master password is the only source of administrative authority.
- Auditability: Every administrative and agent action is recorded in the vault's audit log under the
vault-masteror agent principal. - Binary Discovery: Either the vault is unlocked and visible, or it is a silent directory of encrypted shards.
The system uses a Discovery-first model. If an agent attempts an action not explicitly in its white-list (the "Iron Triangle" of Agent-Key-Action), the dispatch is paused:
// In Agent process
const result = await agent.agentDispatch({ ... });
if (result.status === 'PENDING') {
console.log("Discovery needed: Waiting for owner approval...");
}
// OR: Use the Observer for real-time push (v1.48.4+)
ownerClient.ownerOnPendingDispatch((req) => {
console.log("New discovery request:", req.requestId);
});
// In Owner process (GUI or Script)
const pending = await client.ownerListPendingDispatches();
if (pending.length > 0) {
// Inspect and approve the request, optionally making it permanent
await client.ownerApproveDispatch({
requestId: pending[0].requestId,
permanent: true
});
}npm run build
npm test