Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions apps/api/src/handlers/custom-automations/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,7 @@ customAutomationsRouter.patch('/:id', async (c) => {
existing.createdByUserId ?? adminId(c),
)
: existingTarget,
createdByUserId: existing.createdByUserId ?? adminId(c),
Comment thread
roomote-roomote[bot] marked this conversation as resolved.
});
return c.json({
automation: toApiAutomation(automation),
Expand Down
41 changes: 30 additions & 11 deletions apps/docs/automations.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -85,14 +85,30 @@ conflict resolution, and remove it when a human should handle the conflict
instead. Roomote only tries this on labeled PRs that are still active, and it
skips PRs older than the age cap you set.

Built-in repository scans, audits, issue and CI investigations, PR reviews,
conflict resolution, setup scans, and snapshot maintenance continue to start
tasks directly. Those automations either have no human run-as identity, produce
structured results consumed by another Roomote workflow, or require a sandbox
by definition. Deterministic alert and stats automations that do not need an
agent post their result directly without launching a task.

Roomote is rolling out automation-owned Fast sessions in two releases. This
release adds the principal-aware storage, read, and authorization shape, but
continues writing only human-owned Fast sessions. Built-in and integration
automation principals therefore keep their existing direct-task behavior until
the follow-up release enables deployment-principal capabilities and Session
writes. This keeps one-release rollback safe: the previous version never sees a
new ownerless Session row.

## Custom automations

Create arbitrary scheduled agent runs with:

- a clear **name**
- the **prompt** Roomote should run
- a **cadence** (`every hour`, `every 6 hours`, `daily`, or `weekly`)
- one required **execution target**: **Fast**, a named environment, or **All repositories**
- one required **delegated task scope**: no default environment, a named
environment, or **All repositories**
- an optional **model** override for the runs; the default follows the
deployment task model
- an optional **report destination**: a direct message to the automation owner,
Expand All @@ -101,9 +117,9 @@ Create arbitrary scheduled agent runs with:
Each automation card summarizes its cadence, workspace target, report destination,
creator, and most recent run.

Use **View previous runs** on an automation card to open the task list
filtered to that automation's runs. For a custom automation, the history is
scoped to that specific automation rather than all custom automations.
Legacy ownerless automations that still run directly in a sandbox show **View
previous runs** on their automation card. Owned automation results stay with
their Fast sessions and any tasks delegated from those sessions.

When creating an automation through Roomote chat, ask for **suggested tasks** or
**launchable follow-ups** if qualifying findings should become tasks that
Expand All @@ -121,10 +137,13 @@ five-field cron expression or a natural-language schedule such as “weekdays at
clarification rather than guessing when the recurrence itself is ambiguous.
Custom schedules do not support seconds or cron macros.

On each due tick, Roomote either launches a normal task in the selected
environment (or across all active repositories), or runs the prompt directly in
**Fast** without starting a sandbox. A Fast run can still delegate a normal task
when repository or workspace execution is required.
On each due tick, an owned custom automation starts in **Fast** without a
sandbox. Fast uses integrations directly when that is enough and delegates a
normal task only when repository or workspace execution is required. The
selected task scope controls that delegated task; it does not force every run to
start a sandbox. Legacy automation records whose owner was deleted retain their
previous direct sandbox behavior because there is no user identity that can
authorize a Fast session safely.

Fast runs deliver to every custom-automation report destination: Slack,
Discord, Microsoft Teams, or Telegram, as either a channel/chat or a direct
Expand All @@ -144,9 +163,9 @@ or important findings, meaningful completed results, blockers, and questions
that need input. Routine success, healthy status, and no-change results stay
silent unless the automation prompt explicitly asks for a report in those
cases. The first message starts a thread, later updates continue that same
thread, and you can reply there to talk to the task. There is no progress
chatter in between. Without a destination, the run happens silently and its
results appear only in the task view.
thread, and you can reply there to continue the Fast session. There is no
progress chatter in between. Without a destination, the run happens silently
and its result remains in the stored Fast session.

Unless the prompt asks for a different presentation, custom automation reports
lead with the result, stay concise, and use short Markdown headings and bullets
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export function FastSessionTranscript({
initialMessages,
hasOlderMessages,
canReply,
readOnlyReason,
initialTitle = null,
fallbackTitle = 'Session',
sessionModel = null,
Expand All @@ -66,6 +67,7 @@ export function FastSessionTranscript({
initialMessages: FastSessionMessage[];
hasOlderMessages?: boolean;
canReply?: boolean;
readOnlyReason?: string;
initialTitle?: string | null;
fallbackTitle?: string;
sessionModel?: string | null;
Expand Down Expand Up @@ -289,6 +291,10 @@ export function FastSessionTranscript({
<p className="px-4 pb-2 text-xs text-destructive">{replyError}</p>
) : null}
</div>
) : readOnlyReason ? (
<p className="mx-auto w-full max-w-4xl shrink-0 px-4 pb-4 text-sm text-muted-foreground">
{readOnlyReason}
</p>
) : null}
</MessageUiOptionsProvider>
);
Expand Down
7 changes: 6 additions & 1 deletion apps/web/src/app/(sandbox)/sessions/[sessionId]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,12 @@ export default async function SessionDetailPage({
sessionId={session.id}
initialMessages={session.messages}
hasOlderMessages={session.hasOlderMessages}
canReply
canReply={!session.ownerAutomation}
readOnlyReason={
session.ownerAutomation
? 'Automation-owned sessions are read-only until the next release.'
: undefined
}
initialTitle={session.title}
fallbackTitle={fallbackTitle}
sessionModel={session.model}
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading