# Getting started with Vectros (preview)

> The secure, AI-native backend for your app or your agents — in a few API calls.

## Vectros is in invite-only preview

Vectros is the secure data, document, search, and AI layer you build on — a governed home for structured records and documents, with hybrid (keyword + semantic) search and retrieval-augmented inference, designed compliance-first for regulated and healthcare workloads.

Today it is an **invite-only 0.x preview**. The surface is real and the code below compiles against the published SDK, but the API is pre-1.0 and may still change between releases, access is gated, and you should use **synthetic data only** while in preview. There is no self-serve free tier yet.

**[Request early access](https://vectros.ai/early-access)** — tell us what you're building and we'll get you an invite. (The CTA is "Request early access," not "Start building free" — we onboard preview partners deliberately.)

## Two ways in

1. **Build on the SDK** — install `@vectros-ai/sdk`, construct a client with a token, and call records / schemas / search / documents / inference directly from your app.
2. **No-code via blueprints + MCP** — pick a bundled blueprint, run one `vectros bootstrap` command to provision schemas and a narrow scoped key, then drive it entirely from an MCP-connected agent (Claude Desktop, Cursor, …) or the `app.vectros.ai` reference app — zero app code.

## Step 0 — Request early access & get your key

1. **Request access** at the link above and wait for your invite.
2. Once invited, sign in to the **developer portal** for your tenant.
3. In the portal, **mint a token** (or create a scoped API key) for the data plane. Tokens are bearer credentials scoped to a `(tenant, context)` — keep them out of source control.

**Environments.** The client's `environment` is the API base URL. Use your **staging** base URL while building in preview; switch to the **production** base URL only when your invite covers prod. Your exact base URLs are listed in the dev portal — they look like `https://api.staging.vectros.ai` and `https://api.vectros.ai`.

> Honest note on the bridge token: the CLI / no-code path needs a one-time **Cognito bridge token** minted from the dev portal to authenticate the CLI to your tenant. It's a human step — there is no fully unattended bootstrap in preview.

## Build on the SDK

### Install + construct the client

```bash
npm install @vectros-ai/sdk
```

```ts
import { VectrosClient } from '@vectros-ai/sdk';

// `token` may be a string or a `() => Promise<string>` supplier (the reference
// app uses the supplier form so it can refresh per (tenant, context)).
const client = new VectrosClient({
  token: process.env.VECTROS_TOKEN!,
  environment: 'https://api.staging.vectros.ai', // your portal base URL
});
```

The reference app (`ui/app-vectros-ai/src/api/vectrosApi.ts`) constructs the client exactly this way, passing a `token: () => Promise<string>` supplier so the bearer is resolved (and refreshed) per `(tenant, context)`.

### Your first calls

All snippets below mirror the real, compiling smoke tests in `smoke-tests/tests/records.spec.ts`.

**1. Ping — confirm auth works.**

```ts
await client.auth.ping();
```

**2. Create a schema.** A schema defines a record type, its fields, and how it's indexed. Mark PHI/PII fields `sensitive: true` — those are redacted from audit history at write time, excluded from the search index, and masked on read unless the token carries a reveal scope.

```ts
const schema = await client.schemas.createSchema({
  typeName: 'patient_note',
  displayName: 'Patient Note',
  indexMode: 'HYBRID', // TEXT | SEMANTIC | HYBRID
  allowedSurfaces: ['record'],
  fields: [
    { fieldId: 'name', fieldType: 'string', required: true, searchable: true },
    { fieldId: 'notes', fieldType: 'string', searchable: true },
    { fieldId: 'department', fieldType: 'string', filterable: true },
    { fieldId: 'mrn', fieldType: 'string', sensitive: true }, // PHI — redacted/excluded/masked
  ],
  lookupFields: [{ fieldName: 'mrn', unique: true }],
  capabilities: { auditHistory: true },
});
const schemaId = schema.id!;
```

**3. Create a record.** Use SYNTHETIC data only in preview.

```ts
const record = await client.records.createRecord({
  typeName: 'patient_note',
  schemaId,
  payload: {
    name: 'Jane Doe',
    notes: 'presents with hypertension and complains of chest pain',
    department: 'cardiology',
    mrn: '000-00-0000', // synthetic
  },
});
// Newly created records index asynchronously: indexStatus === 'PENDING_INDEX'.
```

Records index **asynchronously**, so search right after create returns nothing
until indexing finishes. Poll `getRecord` until it reads `INDEXED` first:

```ts
async function waitUntilIndexed(id: string): Promise<void> {
  for (let i = 0; i < 20; i++) {
    const r = await client.records.getRecord({ id });
    if (r.indexStatus === 'INDEXED') return;
    await new Promise((res) => setTimeout(res, 500));
  }
}
await waitUntilIndexed(record.id!);
```

**4. Search it.** One unified call over records + documents; `mode` is `TEXT`, `SEMANTIC`, or `HYBRID`.

```ts
const results = await client.search.content({
  query: 'chest pain',
  mode: 'HYBRID',
  limit: 20,
  // narrow with filters on filterable fields, e.g. { department: 'cardiology' }
});
for (const hit of results.results ?? []) {
  console.log(hit.documentId, hit.semanticScore, hit.textScore);
}
```

**5. Look up by an exact field.** `lookupRecords` returns the FC-01 envelope.

```ts
const page = await client.records.lookupRecords({
  type: 'patient_note',
  field: 'mrn',
  value: '000-00-0000',
});
const found = page.data ?? []; // { data, nextCursor } — FC-01 envelope
```

**FC-01 list envelope.** Every list / lookup / version endpoint returns `{ data, nextCursor }`. When `nextCursor` is non-null, feed it back as `startFrom` and drain in a loop:

```ts
const ids: (string | undefined)[] = [];
let cursor: string | null | undefined;
do {
  const p = await client.schemas.listSchemas(
    cursor ? { startFrom: cursor, limit: 100 } : { limit: 100 });
  ids.push(...(p.data ?? []).map((s) => s.id));
  cursor = p.nextCursor;
} while (cursor);
```

(`search.content` is **not** enveloped — its hits are on `results.results`.)

## No-code via blueprints + MCP

A blueprint is a reviewed, bundled package that provisions a complete, governed data model — schemas, a least-privilege access profile, a service principal, and seed data — in one command. Four ship in the preview:

- **`task-management`** — structured task tracking, shareable across sessions, agents, and users.
- **`coding-agent-memory`** — persistent project memory for a coding agent: decisions, conventions, and gotchas that survive across cold starts.
- **`second-brain`** — a personal knowledge base: capture notes, ideas, and links, then ask them anything by meaning.
- **`clinical-intake`** — a behavioral-health intake with PHI fields, demonstrating redact-at-write, audit history, and search exclusion. Synthetic data only.

**Install the CLI** (`@vectros-ai/cli`, exposes the `vectros` command):

```bash
npm install -g @vectros-ai/cli      # then: vectros bootstrap …
# …or run without installing: npx @vectros-ai/cli bootstrap …
```

**Get a bridge token, then bootstrap.** The CLI authenticates to your tenant with a
one-time **Cognito bridge token** minted from the developer portal at
`https://developer.vectros.ai/settings/cli-token`. Paste it when prompted, pass
`--token <t>`, or export `VECTROS_BOOTSTRAP_TOKEN`:

```bash
npx @vectros-ai/cli bootstrap --blueprint second-brain
```

`bootstrap` is idempotent: it provisions the schemas → a dedicated app context → a service principal → a gated, least-privilege access profile → a narrow `ssk_*` scoped key, then optionally seeds. The scoped key is data-plane-only (records / schemas / search / documents / folders / inference); control-plane scopes are rejected by the blueprint's scope gate.

**Then drive it — zero app code — two ways:**

- **Via an MCP-connected agent.** The `ssk_*` is merged into the MCP server config, exposing data-plane tools (records, documents, folders, schemas, search, RAG) to your agent. Say "capture this thought" or "what did I note about onboarding?" and it reads and writes Vectros directly.
- **Via `app.vectros.ai`.** The reference data-plane app shows your records, runs search, drives AI/RAG inference, and includes an audit **History** view so you can watch versioning (and redaction of `sensitive` fields) on real records.

## Where to go next

Per-blueprint walkthroughs:

- [Coding agent memory](./coding-agent-memory.md)
- [Second brain](./second-brain.md)
- [Clinical intake](./clinical-intake.md)

**Compliance posture.** Vectros is built compliance-first: every write to an audited model emits an immutable, tamper-evident version row; heavy content externalizes to a WORM (Object-Lock) bucket; `sensitive` fields are redacted-at-write (destroyed before the audit snapshot, not reversibly masked) and excluded from the search index; isolation is enforced by a mandatory, auth-derived `contextId` on every row; and the platform has been through two formal security audits. Full compliance detail — and BAA discussion — is available **under NDA** as part of early access.

## Notes

- **Invite-gated.** The preview is invite-only; the CLI / no-code path additionally needs a one-time Cognito bridge token minted from the dev portal.
- **Synthetic data only.** Do not enter real PHI/PII into a preview tenant — every example here uses synthetic data.
- **Staging vs prod.** Build against your staging base URL; move to production only when your invite covers it. The `environment` value is the only thing that changes.
- **Pre-1.0.** This is a 0.x preview; surfaces may change between releases. Some advertised-elsewhere capabilities (turnkey end-subject erasure, configurable retention, data residency, BYOK) are **not** part of the preview — ask us what's in scope for your use case.
