---
name: vinkius-connect-core
description: 'Explains how the Vinkius AI Connect SDK (@vinkius/connect) works internally: one Application key serving unlimited users addressed by your opaque external_id, connectors versus connections versus capabilities, write-only credentials, the per-connection vk_live_* execution runtime, model adapters, retries and the typed error model. Use when writing any code against @vinkius/connect, wiring Vinkius connectors, capabilities, external_id, or per-user AI tool connectivity.'
license: Apache-2.0
metadata:
  author: Vinkius
  package: "@vinkius/connect"
  version: "0.1.3"
  docs: "https://vinkius.com/learn/connect-sdk"
---

# Vinkius AI Connect SDK: how it actually works

This skill teaches the machinery of @vinkius/connect so you can write correct code from your own knowledge. It is the prerequisite for the five build skills. Read it before touching the SDK in a codebase.

## The model in three sentences

One Application (a public `vk_app_*` id plus a secret `vk_app_sk_*` key) serves unlimited users. A user is any entity that should own isolated connections: a person, a team, an agent, a job, or a user inside one of your customers, addressed by YOUR opaque `external_id`. Each user connects catalog connectors; the connected tools of each user are capabilities your model can call, executed per connection, isolated and metered automatically.

## Vocabulary (the SDK never uses other words)

- Connector: one catalog integration (github, slack, and thousands more), maintained by Vinkius.
- Connection: one connector connected for one user. This is the isolation unit.
- Capability: one executable tool a connection exposes, namespaced `connector__name` by default.
- `vk_live_*` data-plane token: minted per connection. Every call through it is metered, and disabling it revokes execution instantly.

## Two planes, one secret

The control plane is REST with the app key: users, connections, credentials, catalog. The execution plane talks JSON-RPC 2.0 directly to the connection's runtime endpoint (`{RUNTIME}/{vk_live_*}/mcp`), which the mcp_url embeds. Listing tools is free; calling a tool is metered against that token. MCP is an implementation detail: your code never names it, it only sees `capabilities()` and `execute()`.

## Semantics you must respect

- `new Vinkius({ appId, apiKey })` validates prefixes eagerly (appId must start `vk_app_` and not be the secret; apiKey must start `vk_app_sk_`), performs zero network, and needs a global fetch (Node 18+). Reuse one instance for the whole process; it is configuration, not a user.
- `vinkius.user(id)` and `user.connector(slug)` are lazy handles: zero requests. Only methods like `connect()`, `set()`, `capabilities()`, `execute()` cross the network.
- `external_id` rules: non-empty string, at most 255 characters, no whitespace, no `/` or `\`, and never a `vk_app_user_*` internal id. `vinkius.user()` and every low-level client enforce this with a ConfigError before any request.
- `connect()` is an idempotent get-or-create that also provisions exactly ONE token. The returned connection carries `runtime_url`; that URL embeds the live token and is handed back ONLY here. The SDK memoizes it and never silently re-mints: a revoked token fails closed as an AuthError instead of quietly billing a fresh one.
- `user.capabilities()` lists the user's connections once, keeps only connectors whose status is `ready`, then fans out tool listing per connection with bounded concurrency (8). It is failure-tolerant: one broken connector is skipped and can be observed via the `onConnectorError(slug, error)` callback; only if every connector fails does it throw. Pass `include`/`exclude` connector slugs to scope the model's tool set; filtering happens client-side before any call.
- `user.ensure(metadata?)` upserts the user (attach non-secret metadata like `kind` or plan). `user.connectors()` returns `{slug, status}` summaries; status is derived from the backend's readiness and is one of not_connected, needs_credentials, ready, disabled.
- Credentials are WRITE-ONLY: `set(values)` stores them (validated against the connector's schema) and nothing, anywhere, returns values back, not the SDK, the model or a dashboard; `status()` only reports which keys are configured. `credentials.schema()` reads the catalog (cached, no connection needed) so you can render the right form fields before anyone connects. OAuth connectors need no `set()` at all: `connect()` returns after the provider consent completes.
- `capability.execute(args, opts)` routes to that user's connection. A tool-level failure is NOT an exception: you get a result with `isError: true` and `content` blocks, which you should hand back to the model so it can recover. Optional `structuredContent` surfaces typed payloads verbatim. Per-call opts: `timeoutMs` overrides the client deadline; `signal` composes with it; `idempotencyKey` is what makes even a POST retry-safe.
- Adapters live in subpath exports (openai, anthropic, gemini, ai-sdk, langchain, llamaindex, openai-agents, workers-ai, json-schema). Each `toXTools(capabilities)` converts to that framework's shape and validates tool-name rules up front (OpenAI 64 chars of `[A-Za-z0-9_-]`; Gemini letters/underscores only): when a namespaced name would be rejected, set `namespaceCapability` on the client instead of catching a provider 400. The dispatch helpers (`runOpenAIToolCall`, `runAnthropicToolUse`, `executeByName`) execute WITHOUT idempotency, timeout or abort controls, so never use them for mutating calls: resolve the capability yourself and call `execute` with the controls.
- Errors are a typed `VinkiusError` subclass tree with stable `code`, `status` and `requestId`: ConfigError, AuthError (401/403), NotFoundError (404, also how cross-tenant access looks), ValidationError (422, with `.errors`), RateLimitError (429 control-plane, `.retryAfterMs`), QuotaError (429 data-plane, `.upgradeUrl`), OverageError (402, `.upgradeUrl`), ConnectorNotConnectedError (thrown only by connector operations on an unconnected handle; it does not name the connector, you already know it), ConnectionError (network/timeout/abort), ProtocolError (wire violations).
- Retries are automatic, never surprising: idempotent methods (GET/PUT/DELETE) plus any call carrying an `idempotencyKey`, on 429/502/503/504 and network errors, full-jitter backoff, server `Retry-After` honored when > 0. Token minting and the runtime `tools/call` are never retried without a key.
- Hooks (onRequest/onResponse) are observability only: Authorization headers, credential-shaped fields and `vk_live_*` path segments are redacted before your callback sees anything. Treat them as audit sinks, not as a place to rebuild secrets.
- The low-level clients (`users`, `connections`, `credentials`, `catalog`, `tokens`) mirror the API 1:1 and are what the fluent layer uses under the hood; prefer the fluent API. Catalog also offers `search()` (marketplace ranking) and page iterators.

## The security posture to assume in every design

The SDK runs server-side only: the app key and `runtime_url` must never reach a browser bundle, a mobile binary or a model prompt. `external_id` must be resolved from your authenticated session, never accepted raw from a request body. Your users' identities (emails, names, profiles) never travel to Vinkius: the platform only ever sees the opaque id your backend passes. That is the customer-relationship boundary, keep it.

## Where to learn more

Docs: https://vinkius.com/learn/connect-sdk (introduction, architecture, reference, errors, security). npm: @vinkius/connect. Build-specific skills: vinkius-multi-user-chatbot, vinkius-department-copilots, vinkius-agent-fleet, vinkius-service-account-automation, vinkius-multi-tenant-saas.
