Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
e76e996
Add the schema, migration and contracts for proactive check-ins
davidmckayv Oct 30, 2026
035d146
Run a started check-in item as a task in its own conversation
davidmckayv Oct 30, 2026
6117e56
Check in quietly and ping each person at most once an hour
davidmckayv Oct 30, 2026
5a936e6
Merge slice A: check-ins and the hourly ping
davidmckayv Oct 30, 2026
809fb4e
Show what check-ins found and the tasks started from them in the app
davidmckayv Oct 30, 2026
67f56c0
Wire check-ins and tasks into the server, prune their ledger, count a…
davidmckayv Oct 30, 2026
3f7ed10
Merge slice D: the app
davidmckayv Oct 30, 2026
1fce8cd
Count a task's wait once across server and app, and call it Check-ins
davidmckayv Oct 30, 2026
048901c
Fix check-in settings, Run now after a skip, and how a check-in task …
davidmckayv Oct 30, 2026
cf827b3
Offer no Always allow on a check-in task's approvals
davidmckayv Oct 30, 2026
3e4b140
Check in on everything the person connected, and only read it
davidmckayv Oct 31, 2026
0c8541e
Deliver each check-in ping to the person's phone, chat and app, and o…
davidmckayv Oct 31, 2026
6131116
Merge branch 'david/proactive-s4' into david/proactive
davidmckayv Oct 31, 2026
9122984
Wire check-in pings into the delivery router
davidmckayv Oct 31, 2026
e78561f
Let admins turn check-ins off, cap them per Bot, and see how they land
davidmckayv Oct 31, 2026
c5dab03
Merge branch 'david/proactive-s5' into david/proactive
davidmckayv Oct 31, 2026
6cfc7b8
Wire the admin Check-ins switch, daily cap and activity route
davidmckayv Oct 31, 2026
779debe
Never post a check-in ping as a Bot the person silenced
davidmckayv Oct 31, 2026
57332aa
Routing settings tests: the server always answers for pings
davidmckayv Oct 31, 2026
e708779
Merge branch 'david/proactive-fix2a' into david/proactive
davidmckayv Oct 31, 2026
e61b169
Routing settings test: four kinds of update, three channels not set up
davidmckayv Oct 31, 2026
c80b841
Record check-ins by what they read, and raise each thing once per person
davidmckayv Oct 31, 2026
37092e4
Recent deliveries name each kind and channel in plain words
davidmckayv Oct 31, 2026
12449a3
Count a Bot's check-in items as things that need you
davidmckayv Oct 31, 2026
9031ae4
Name an app's approval by its action and the app
davidmckayv Oct 31, 2026
618246e
Draw the phone's Needs you rows like the app's other screens
davidmckayv Oct 31, 2026
870906e
Let a check-in task ask once before each step, read the person's own …
davidmckayv Oct 31, 2026
879de6a
Merge branch 'david/proactive-fix3a' into david/proactive
davidmckayv Oct 31, 2026
dac1086
Merge branch 'david/proactive-fix3b' into david/proactive
davidmckayv Oct 31, 2026
b38c31d
Merge branch 'david/proactive-fix3c' into david/proactive
davidmckayv Oct 31, 2026
e7225e3
Merge remote-tracking branch 'origin/main' into david/proactive
davidmckayv Oct 31, 2026
bf7d3bf
Changelog: Bots tell you when something needs you
davidmckayv Oct 31, 2026
5690836
Merge remote-tracking branch 'origin/main' into david/proactive
davidmckayv Nov 2, 2026
ca6ce61
Tag every ask in a check-in task as the task's
davidmckayv Nov 2, 2026
ff79b9c
Run only reviewed reads unasked in a check-in task
davidmckayv Nov 2, 2026
c7e16c6
Assert the Parallel entry names no reads without an optional-chain su…
davidmckayv Nov 2, 2026
39bf008
Carry a built-in Bot's run on its tools instead of matching call ids
davidmckayv Nov 2, 2026
063d583
Decide whether a task's looks ask from the server, for the thread
davidmckayv Nov 2, 2026
be8b3fd
Page the ping pass past people an admin turned check-ins off for
davidmckayv Nov 2, 2026
c3c3e74
Close a check-in as failed whatever stops its bookkeeping
davidmckayv Nov 2, 2026
6c15cc3
Carry a retried task turn on the same ask
davidmckayv Nov 2, 2026
7759494
List the catalogue once per check-in
davidmckayv Nov 2, 2026
6f9545a
Share the Always allow predicate between server and browser
davidmckayv Nov 2, 2026
af4f909
Answer the conversation check in the help hand-back fake
davidmckayv Nov 2, 2026
0c2a55d
Merge remote-tracking branch 'origin/main' into david/proactive
davidmckayv Nov 2, 2026
586b34a
Type the recorded request body in the approval-tools test as optional
davidmckayv Nov 2, 2026
27829a3
Merge remote-tracking branch 'origin/main' into david/proactive
davidmckayv Nov 2, 2026
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,27 @@ Newest first. `Unreleased` is what is on `main` and not yet tagged.
In the all-in-one image that share counts the database and the API server too.
`COMPUTER_MEMORY_HIGH_PERCENT=0` and `COMPUTER_TAB_IDLE_MS=0` (Helm: `computers.memoryHighPercent`
and `computers.tabIdleMs`) keep the old behaviour.
- Bots now check in on their own and tell a person when something needs them (below). It is on by
default for every Bot a person has talked to. Migrations `0071_proactive_check_ins` and
`0072_check_in_read_labels` add its tables. Admin → Check-ins turns it off for everyone.
- Migration `0070_memory_dedup_per_bot` rebuilds one unique index on `personal_memories` to include
the Bot that formed the memory (below). It keeps every row. While it rolls out, a server still on
the previous release fails to save a newly formed Bot memory until it is replaced; nothing else is
affected.

### Bots tell you when something needs you

A Bot a person has talked to now checks what that person connected (any app or server they
connected with their own account), quietly and at most once an hour, and only reads. When it finds
something that needs the person, it says why and where it came from, and the person hears about it
at most once an hour, with every Bot's items in one message: in the app (Needs you, a badge and a
browser notification), by phone push, and on Slack, Teams or SMS where the person already talks to
a Bot. Nothing is sent when nothing needs them. Start turns an item into a task that asks before
every send or change; Hide keeps it from coming back for 30 days. A person turns it off in Settings
→ Notifications and chooses where these go under "Something needs you"; an admin turns it off for
everyone, changes the daily limit (24 check-ins per Bot) and sees how often items are started under
Admin → Check-ins.

### Each Bot keeps a fact it formed, even when another Bot formed it first

A memory a Bot forms from what it read was deduplicated per person, but each Bot recalls only the
Expand Down
6 changes: 6 additions & 0 deletions app/src/components/admin/admin-sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
IconLayoutGrid,
IconListDetails,
IconPuzzle,
IconRadar,
IconShieldCheck,
IconSlash,
IconUsers,
Expand Down Expand Up @@ -88,6 +89,11 @@ const GROUPS: {
icon: IconBulb,
linkOptions: { to: "/admin/learning" },
},
{
title: "Check-ins",
icon: IconRadar,
linkOptions: { to: "/admin/proactive" },
},
{
title: "UI components",
icon: IconLayoutGrid,
Expand Down
17 changes: 12 additions & 5 deletions app/src/components/approvals/inline-approval.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { offersStandingRule } from "@openbot/shared/standing-rule";
import { approvalWords } from "@openbot/shared/tool-name";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import type { ReactNode } from "react";
import { Button } from "@/components/ui/button";
Expand Down Expand Up @@ -35,14 +37,22 @@ export function InlineApproval({
: undefined;
if (request?.status !== "pending") return <>{fallback}</>;
const handOff = request.action.policy?.behaviour === "hand_off";
const words = approvalWords(request.action);
const choices: [ApprovalDecision, string][] = handOff
? [
["handled", "I did it myself"],
["deny", "Don't do it"],
]
: [
["allow_once", "Allow once"],
["allow_always", "Always allow here"],
...(offersStandingRule(request.action)
? [
["allow_always", "Always allow here"] as [
ApprovalDecision,
string,
],
]
: []),
["deny", "Deny"],
];
return (
Expand All @@ -52,10 +62,7 @@ export function InlineApproval({
>
<p className="font-medium">
{handOff ? "This needs you" : "Waiting for your approval"}:{" "}
{request.action.toolRef
.replace(/^computer_|^host\//, "")
.replaceAll("_", " ")}{" "}
on {request.action.scope}
{words.action} on {words.place}
</p>
{request.action.policy ? (
<p className="text-muted-foreground">{request.action.policy.reason}</p>
Expand Down
Loading
Loading