> ## Documentation Index
> Fetch the complete documentation index at: https://docs.r5d.chat/llms.txt
> Use this file to discover all available pages before exploring further.

# Private automation authoring

> Build owner-approved private commands with durable triggers and safe external confirmations.

Private automations run in the execution owner's workspace. They can check a site, interpret a bounded event, or perform an explicitly approved action. They are **not public application hosting**: no workspace-port publication, tenant HTTP proxy, HTML response, or public result/inference API. A platform webhook only authenticates and durably accepts an event with a fixed acknowledgement. Public apps belong on a separately authorized hosting provider.

## Start with a tested draft

Ask the agent to read `/opt/r5dchat/skills/private-automations/SKILL.md`. The source distribution includes a fixture-only reference in `examples/private-automations/`; it is not a preconfigured live connector.

Use the installed CLI help as the version authority. The authoring flow is:

```sh theme={null}
r5dchat automations validate --file definition.json
r5dchat automations create --file definition.json --idempotency-key setup-001
r5dchat automations activate AUTOMATION_ID --version VERSION_ID
r5dchat automations inspect AUTOMATION_ID
```

The agent configures the saved immutable definition through the automatically authenticated owner CLI: project/chat, purpose, code revision, trigger/timezone, recipients, secret references, allowed actions and limits. There is no second browser approval gate or manual CLI token setup. Background credentials cannot expand authority. If this installation has a capability disabled or unavailable, keep the draft and report it rather than using database/admin workarounds.

After approval, a supported command run can carry typed JSON data without shell interpolation:

```sh theme={null}
r5dchat runs submit --automation AUTOMATION_ID --version VERSION_ID \
  --input-file input.json --idempotency-key check-cycle-001 --detach
r5dchat automations disable AUTOMATION_ID
```

CLI data is JSON/NDJSON. A durable submission returns run/chat identifiers; follow observes that same run, and detaching does not cancel it. Inspect the outcome and remote evidence, not just terminal status or process exit zero. `needs-input` means the automation finished and awaits a new input; `needs-attention` means recovery or owner review is required. Cancelling does not undo already dispatched remote actions.

Interactive owner shell access uses a short-lived server-issued owner identity. Refresh rotates it in place with a fixed one-day deadline and a private mode-0600 CLI store. Background work uses a separate revocable delegated execution token, never a saved browser cookie or daemon administration token. Background credentials cannot enlarge grants or approve themselves. Never print or commit execution credentials. CLI/executor end-to-end acceptance is a separate gate from running the standalone fixture tests below.

## Code and private state

Use a dependency-locked/bundled release at `/home/r5d/.r5dchat/automations/<id>/releases/<digest>/`, with explicit cwd/argv and a manifest. Missing/changed files or incompatible dependencies fail visibly. Material changes create a new version and require review. Keep mutable SQLite data, logs and any browser profile outside release directories. Release immutability improves reproducibility; it is not a security sandbox against root-capable processes of the same owner.

Keep secrets, state and browser profiles out of Git, shared artifacts, broad indexing and routine diagnostics. Back up SQLite consistently with its WAL (use a SQLite backup operation or stop writers); do not copy only a live database file. Restore automations paused and reconcile remote effects before resuming. Retain event/callback tombstones so history cleanup cannot silently reauthorize old selections.

## Credentials and browser setup

Declare credential names and inspect metadata. Supply authorized private values through stdin/file, never command arguments or chat:

```sh theme={null}
r5dchat secrets declare --name TELEGRAM_BOT_TOKEN
r5dchat secrets declare --name TELEGRAM_WEBHOOK_SECRET
r5dchat secrets status
r5dchat secrets set SECRET_ID --file /private/token.txt
r5dchat secrets rotate SECRET_ID --stdin
```

A real site may need its own declared credential. The declaration itself contains no value. Bind only approved references, inject values at runtime, redact logs and support rotation/revocation. Code that receives a secret can read it; do not promise the same-owner workspace cannot inspect it. Never request real site credentials for platform development.

Prefer HTTP APIs. When needed, use worker-side Playwright with reproducible browser dependencies and an explicitly owner-authorized private persistent profile. The product must not assume the development environment's signed-in browser is available. Do not copy cookies into Playwright. Reauthentication must use a supported secure setup path; if none exists, stop as needs-input. CAPTCHA, MFA, expired sessions and blocked sites require owner intervention, not bypassing or unattended retries. A live feasibility check or booking needs separate authorization.

## Telegram and exact-slot authorization

Use a user-provided bot. Never replace an existing bot webhook without explaining the change and obtaining approval. Register events through supported platform controls, not a public listener in the workspace. Provider secret-token verification authenticates delivery; it does **not** authorize the Telegram sender.

The owner starts linking and receives an expiring single-use challenge. Bind the challenge to the authenticated owner and intended Telegram sender/private chat, store its hash, and accept only the owner's user-initiated `/start <challenge>`. Reject mismatched sender/chat, groups, bots, replayed or expired challenges. New recipients require new approval.

Persist each availability proposal's exact slot IDs/revisions, dates/timezone, expiry, recipients, version and cycle correlation. Send buttons, then exit. An authenticated reply creates a new correlated run, with transactional `update_id` and callback deduplication. Untrusted page/event instructions never expand authorization; ambiguous free text asks for clarification. Expired, consumed, missing or changed choices require fresh suggestions and a new exact selection—not an alternative booking.

Before a booking: atomically consume the selection, persist an external-action intent, serialize competing choices, and recheck exact availability and existing reservations. Persist dispatch before the request. Report success only after a matching remote reservation is independently verified. If interrupted after remote booking but before local commit, reconcile the reservation rather than repeating the request. Missing/unavailable reconciliation means manual attention, not a blind retry.

**Notifications and bookings differ.** A Telegram send accepted before a lost response/local commit may be duplicated during explicit recovery. Keep a separate delivery ledger. Repairing a notification must never replay its booking.

## Schedules, limits and operation

Clarify every 72 elapsed hours versus every third local calendar day and use an explicit IANA timezone. Preview upcoming occurrences and DST transitions before activation; day-of-month `*/3` is not every three days. Scheduled runs may overlap; `overlapPolicy` defaults to `allow`, and legacy `skip` is accepted for stored-definition compatibility without suppressing active overlap. Keep fresh missed-check coalescing and no burst of old checks on resume. Scheduled checks and webhook replies need no always-on process.

Bound runtime, input/output, tokens, recursion and retention. There are no per-owner/per-automation active or queued run caps. Persist waiting state instead of retaining an executor or model request. Use inspect/history and in-app attention signals independently of Telegram, and keep owner pause/disable/credential-repair controls reachable.

## Reference verification and limits

From a source checkout with locked dependencies installed:

```sh theme={null}
bun test examples/private-automations/reference.test.ts
```

This suite starts real Bun command processes against literal-loopback fake Telegram/site HTTP servers. It kills processes at durable boundaries, reopens the same private SQLite state and verifies actual HTTP request counts and reservations. It tests process-free waiting, two-choice races, expired/consumed/version-changed proposals, sender/chat authorization, linking expiry, event/callback dedupe, prompt injection, unknown outcomes, and duplicate notification versus single booking.

The reference rejects production origins and `testMode: false`. Fixture effects require an explicit local test interlock, which is not platform approval authority. It never changes a bot webhook, calls a live provider/site, or proves a real site's feasibility. Platform scheduler/webhook/executor recovery and owner-CLI setup must also pass their integration suites before unattended activation is claimed.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.