# Deploy the OrgVault connector bot — instructions for an LLM operator You are helping a verified human administrator install a connector **on infrastructure they control**. OrgVault stays hosted at https://orgvault.md. Read [the connector guide](/connectors.md) first. Do not deploy this connector into OrgVault's AWS account or ask OrgVault to hold source/LLM keys. ## 1. Agree on the import boundaries Obtain the human's organization ID, responsible human, enabled sources, allowed source folders/records, permitted topics and excluded information, desired Markdown layout, destination folder prefixes/classification, polling interval (default 30 minutes), model/provider endpoint and limits. Confirm who can read each destination through existing OrgVault grants. A folder name alone does not restrict readership. Use read-only source keys with the smallest available access scope. Let the human enter keys directly into their local secret manager or private environment file; never request keys in chat, logs or source control. Explain that filtered source content is sent to their configured LLM endpoint, and that LLM confidentiality judgments can be wrong. If that transfer is not permitted, choose an approved local compatible model or stop before model use. ## 2. Download and inspect Use Node.js 22 or later on macOS/Linux, or Linux containers. POSIX file permissions are required; use WSL/Linux containers on Windows. ```sh mkdir -m 700 orgvault-connector cd orgvault-connector curl --fail --silent --show-error https://orgvault.md/downloads/orgvault-connector.zip -o connector.zip curl --fail --silent --show-error https://orgvault.md/api/v1/connectors -o manifest.json node --input-type=module -e 'import fs from "node:fs"; import crypto from "node:crypto"; const m=JSON.parse(fs.readFileSync("manifest.json")); if(crypto.createHash("sha256").update(fs.readFileSync("connector.zip")).digest("hex")!==m.sha256) throw new Error("Package checksum mismatch"); console.log(m.version)' unzip connector.zip cp config.example.json config.json mkdir -m 700 private cp connector.env.example connector.env chmod 600 connector.env config.json ``` A checksum verifies package/manifest agreement over HTTPS, not a separate signature. If mismatched during an upgrade, fetch both again and inspect before running. Review the code, configuration and packaged license. No `npm install`, global package, inbound port or cloud resource is required. ## 3. Create a dedicated human-linked bot with narrow grants ```sh node agent-client.mjs register --identity private/agent.json --name KnowledgeConnector --workspace ConnectorHome node agent-client.mjs public-key --identity private/agent.json --raw ``` Save the generated recovery backup separately and securely. Registration creates the bot's personal home, not a shared corporate organization. In the existing organization's **Console → Account and billing → Invite a bot**, the human administrator enters this public key, a bot name, their responsible human ID (blank assigns the verified administrator), and a folder scope such as `/integrations`. Set the maximum classification to match the configured routes. This invitation grants only `resource:read` and `resource:write`, with no administration or public-post permissions. Save the returned invitation JSON as `private/invitation.json`, mode 600, then accept: ```sh chmod 600 private/invitation.json node agent-client.mjs accept --identity private/agent.json --invitation private/invitation.json ``` The invitation is bound to the signing key, server, organization and active verified human. Delete the token file after success. If acceptance had an uncertain response, do not create another identity: obtain a fresh home session, then the organization's session through the signed API (or Python client's `org session` command). Existing bound grants remain the limit. The console currently issues an invitation valid for one day and access for 30 days; schedule an access review/renewal before expiry. Removing the responsible human revokes all their org bots. Do not use domain auto-join for this dedicated ingestion bot if it would grant broader access than the intended folders. An API-based administrator may supply several read/write grants to `/api/console/bot-invitations`, instead of one common prefix. No new billing rate is introduced by a connector bot. ## 4. Configure folders and preview Edit `config.json`: fill the real org ID, select only needed sources, narrow source filters, adjust rules/routes, and choose the model. Never use the example model text as a real model name. Put keys into `connector.env` locally. For native Node, load the file with `--env-file` (not a shell `source`): ```sh node --env-file=connector.env connector.mjs check --config config.json node --env-file=connector.env connector.mjs preview --config config.json ``` Before formatting, follow [the folder convention](/folders.md). With the configured rules and destinations approved, initialize missing folder instructions (this writes private OrgVault files but does not call a source or LLM): ```sh node connector.mjs init-folders --config config.json ``` It creates `spec.md` and `index.md` at configured destinations and writable ancestor levels, preserving existing specifications. Review/refine the generated specs and ensure the applicable parent indexes list their child folders. Have an authorized administrator maintain inaccessible ancestors; do not widen the ingestion bot's grants. The poller reads these specs to determine formatting and stops if a required spec is missing. Keep each destination index at the same classification/readership as its managed files. `check` validates local config and required environment variables; it makes no network calls and does not prove source credentials/grants work. `preview` reads sources, applies deterministic filters and writes eligible content into a new private `connector-state/preview-TIMESTAMP` directory. It makes no LLM calls or OrgVault writes. Review these files locally. A full-page failure appears in JSON logs/status and must be addressed before proceeding. Only after the human approves sending selected content to that model, test formatting (this may cost money): ```sh node --env-file=connector.env connector.mjs preview --config config.json --with-llm ``` The paid formatting preview also reads the destination and accessible ancestor specifications from OrgVault. Inspect the formatted JSON locally. `review`/`skip` counts mean nothing was published; there is no automatic manual-approval bypass. Adjust source/rules and rerun preview if needed. Preview does not mark production items delivered, and its LLM attempts count toward the same daily budget. Delete private preview directories after review; they can contain source text. ## 5. Enable publishing and run a service After the human approves the exact rules, source/model data flow and destinations, set `mode` to `publish`. Run one cycle, inspect its resulting private files and scope, then start continuous operation: ```sh node --env-file=connector.env connector.mjs once --config config.json node --env-file=connector.env connector.mjs run --config config.json ``` For persistent operation, use the supplied Docker Compose service with the same private directory. On Linux, set `CONNECTOR_UID`/`CONNECTOR_GID` to the owner of that directory before Compose so its non-root user can write state/identity: ```sh export CONNECTOR_UID="$(id -u)" export CONNECTOR_GID="$(id -g)" docker compose build docker compose run --rm connector check --config /run/orgvault/config.json docker compose up -d docker compose logs --tail 30 connector ``` The native relative paths `./private/agent.json` and `./private/connector-state` also resolve correctly inside the container. The container has no inbound ports, a read-only application filesystem, a private writable data mount and rotating logs. The image build downloads the Node base image; this is not an OrgVault-hosted runtime. Keep the host and runtime patched. For local models from a container, provide a reachable HTTPS endpoint; host loopback is not container loopback. If Docker is unavailable, install the `run` command in the machine's existing supervisor (launchd/systemd) with an absolute Node/config path, private environment access and restart-on-failure. Do not create a second cron schedule alongside the built-in poller. No process should keep the same identity file open concurrently. ## 6. Operate and recover ```sh node connector.mjs status --config config.json docker compose stop ``` Monitor last-poll time, error counts, source/item hashes, daily attempted calls and pending scans. Logs omit source bodies, provider responses and keys. The runtime reports fixed error codes: authentication/permission HTTP status, `provider_backoff`, `llm_budget_exhausted`, `destination_conflict`, `destination_removed`, `unsafe_llm_result`, or `state_capacity_reached`, `folder_spec_missing`, or `invalid_index_markers`. It retries bounded read requests on short rate limits; paid model calls and writes are reconciled on later polls. After the daily call limit, wait for the next UTC day or deliberately adjust the configured budget. Limits are local to this state directory, not an account-wide dollar cap. Use source IDs and hashed item IDs to investigate inside the local state and source UI. Correct malformed permissions/rules/items rather than deleting state. Conflict resolution must preserve any manual edits; choose a new destination prefix when a managed document should no longer be updated. Review old copies separately. A stopped/crashed process may leave `run.lock` or `agent.json.lock`: verify no process/container is running before removing only those locks. Atomic outbox/state writes allow the next process to reconcile uncertain uploads by exact content hash. Back up identity and state together under the organization's local data policy; old backups can contain pending Markdown. Preview cleanup and local backups are the administrator's responsibility. Before upgrading, stop the service, privately back up config/identity/state, verify the new package checksum, inspect changes, run `check` and preview, then restart. Config/state version 1 is required; unsupported versions stop safely. Source/API schema changes and model compatibility must be tested with the organization's real credentials by its administrator. The package's automated tests use simulated provider responses; no production source account or paid LLM was used to activate your integration.