Skip to main content
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:
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:
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:
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:
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.