Repository navigation
[agora-fake-strategist] Add latest-window reads so the timeline and inboxes keep showing new events #8
Copy link
Copy link
Open
Description
Latest verdict
- Status:
VALID - Checked at:
2026-10-27T00:04:02Z - Evidence:
mainis still 2f3ddab, and nothing has merged since the last check. There are no open PRs (#1 through #7 are merged), and this issue has no assignees or comments. The only other open issue, #5 (browser token auth), was last refreshed at 2026-10-26T09:00Z with no scope change and does not overlap. No Agora or Kelos issue or PR proposes newest-first reads. Every permalink below still points at the code it names.make verifyandmake buildpass.- Reproduction, rerun with fresh
mainbinaries: 25 sessions each postedsummary,code_changed,tests_passed, andhandoff. A human replied to each handoff with the payload the browser's Reply button sends, acommenttargeted at@codex-one, and then posted oneinstructiontocodex-one, for 126 events in total.GET /api/events?limit=100ends atRe: Handoff task-20, the README'slimit=50example ends atRe: Handoff task-10, andlatest=trueis still ignored, so it returns the same window. The defaultAGORA_AGENT=codex-one agora inboxexits 0 and prints 20 stale items, fromRe: Handoff task-1toRe: Handoff task-20, without the instruction. Only the UI inbox panel (open=true) shows it, and in the timeline onlylimit=500reaches it. - Alternatives rechecked, none clearly stronger:
loadstill uses a defaultbufio.Scanner, whilereadJSONaccepts bodies up to 1 MiB. Rerun today, a 70 KB post returns HTTP 201, and the next start exits 1 withread store: bufio.Scanner: token too long. That needs an unusually large post, while this slot's problem hits every deployment in normal use./api/healthzstill returns 401 whenAGORA_TOKENis set. The Kubernetes example probes that path but sets no token, so this only affects token-protected deployments. - Kelos activity since the last check: kelos-dev/kelos#1249 gained commit eb9bb35 (2026-10-26T18:07Z), a one-line edit to the Kelos
AGENTS.mdrule on CRD API versioning. kelos-dev/kelos#1734, kelos-dev/kelos#1420, and kelos-dev/kelos#1664 have had no activity since then. Kelosself-development/agora/has not changed since 3040ff1 (2026-10-15). None of these touches Agora's product surface. Following kelos-dev/kelos#1420, this refresh rebuilt the body from the raw JSONbodyand changed only this verdict block, including trailing whitespace.
- Reproduction, rerun with fresh
Area
New API, UI, or Deployment Capabilities (timeline and inbox read model)
Candidate
Add an opt-in latest=true query parameter to GET /api/events and GET /api/agents/{agent}/inbox. It returns the newest limit matching events instead of the oldest. Then make the browser UI and agora inbox use it, so new posts and new instructions stay visible after the log grows past a page.
Why this should be the next strategic priority
- Every deployment hits it in ordinary use. The skill's required loop posts at least 3 to 5 events per agent session. 100 events is about 20 to 25 sessions, which is about a day for one developer running a few agents. A shared team or Kubernetes server reaches it sooner.
- It breaks the loop Agora exists for, and it is silent. A human posts an instruction, and it shows as posted. The agent's
agora inboxreturns a non-empty list of stale items, so the agent never sees the instruction and has no hint that anything is missing. In the browser's default all-threads view, the human's own post disappears after they click Post. - Growth makes it worse. Per-session threads,
@allCI broadcasts, more agents, and long-lived servers all add events.clampLimitcaps reads at 500, so once the log passes 500 events, no single request can return the newest one. The only way to reach new events is to page through the whole history withafter. - It blocks integrations. Any CI bridge, chat relay, or dashboard that wants "what is new" faces the same problem: it must page through the full history first.
- The fix is small and additive. A prototype changes 5 code files (+14/−4 lines, before the stderr note and new tests) plus the README, with no change to storage, response shape, or default behavior.
Current behavior
ListEventsiteratess.events[start:]from the oldest event and stops afterlimitmatches (default 100, max 500).after=<id>is the only cursor, and it pages forward.- The browser UI requests
/api/events?limit=100for the timeline and/api/agents/{actor}/inbox?open=true&limit=100for the inbox. Both get the oldest 100 matches. The inbox panel filters toopenandacknowledged, which excludespostedcomments, so it falls behind only after more than 100 open or acknowledged items. The timeline andagora inboxfall behind first. agora inboxdefaults to--limit 20and to the statusesposted,open, andacknowledged. The server filters by status before applying the limit, asTestInboxStatusFiltersBeforeLimitrequires, but it still returns the oldest 20.- Inbox items that are never closed pile up in normal use:
- Browser replies: a reply targets the post's author as a
comment, which defaults toposted. Replies to ahandoffarrive after the agent session that could have closed them has ended. @allbroadcasts: these land in every agent's inbox. Status is shared, so one agent closing a broadcast hides it from all the others, which gives agents a reason to leave FYI posts open.
- Browser replies: a reply targets the post's author as a
- The README's "List the timeline" example,
?limit=50, returns the oldest 50 events.
Reproduce with the CLI:
agora-server &
# 24 sessions: eval "$(agora session)"; post summary, code_changed, tests_passed, handoff
# For each handoff, the human replies from the browser (a comment targeted at @codex-one)
curl -X POST $AGORA_URL/api/events -d '{"type":"instruction","actor":"human","title":"Stop: do not merge task-25","targets":["codex-one"]}'
curl "$AGORA_URL/api/events?limit=100" -> events 1..100, the new instruction is missing
AGORA_AGENT=codex-one agora inbox -> 20 old "Re: Handoff" comments, the new instruction is missing
Proposed design
1. API and store: latest=true
GET /api/eventsandGET /api/agents/{agent}/inboxacceptlatest, parsed the same way asopen(parseBool).- With
latest=true, the server applies every existing filter (thread,reply_to,status,open, agent,after), then returns the newestlimitmatches. - The returned array stays in chronological order, oldest to newest within the window. The UI builds reply trees from array order (replies oldest-first, from #2), and the CLI prints in array order, so neither has to re-sort.
after=<id>stays a lower bound:after=X&latest=truereturns the newest matches afterX.- In the store, add
EventFilter.Latest.ListEventsscans backward from the end, collects up tolimitmatches, and reverses them. The worst case stays O(N), as it is today.
The parameter is opt-in rather than a new default for two reasons. Forward pollers that use after=<last seen>&limit=N need oldest-first reads; with a newest-first default they would silently skip events whenever more than N arrive between polls. And existing scripts keep exactly the responses they get today.
2. Browser UI
- Timeline:
/api/events?limit=100&latest=true[&thread=...]. - Inbox panel:
/api/agents/{actor}/inbox?open=true&limit=100&latest=true. buildEventTreealready renders a reply as a root when its parent falls outside the window, so no other UI change is needed.
3. CLI: agora inbox
- Send
latest=truein every mode: default,--open, and--all. - When the server returns as many items as the effective limit (
--limit, or 500 when--limitis larger, becauseclampLimitcaps it), print one line to stderr, for example:agora inbox: showing 20 items; more may exist, rerun with a larger --limit. The wording stays neutral because an older server that ignoreslatestreturns the oldest items. The stdout format does not change.
4. Docs
- In the README's API section, document
latestand change the timeline example to?limit=50&latest=true. - No
skills/agora-reportingchange is needed, because the skill callsagora inbox, which picks up the new behavior.
Compatibility
- Requests without
latestreturn exactly what they return today, includingafterpaging. - The response shape stays the same: a JSON array of events.
- A newer CLI against an older server still works.
filterFromQueryignores unknown query parameters, so the request falls back to today's behavior with no error. An older CLI against a newer server behaves as it does today. - The UI is embedded in the server binary, so it always matches the server.
- No JSONL record, store format, environment variable, Kubernetes manifest, or skill contract changes.
Out of scope
- A
before=<id>cursor and a "Load older" control in the UI. History stays reachable through default oldest-first reads withafter, and through the thread filter. - Per-recipient status for multi-target and
@allevents. - Long-polling or push delivery for inboxes.
- Raising the 500 cap, or adding totals or
has_moreto responses, which would change the response shape.
Acceptance criteria
ListEventswithLatestreturns the newestlimitmatching events in chronological order. Thethread,reply_to,status/statuses,open, agent, andafterfilters still apply first.- Without
latest,GET /api/eventsand the inbox endpoint return the same results as today, and the existing tests pass unchanged. - With more than 100 events in the log,
GET /api/events?limit=100&latest=trueincludes the most recently posted event. The inbox endpoint behaves the same way with status filters, and status filtering still happens before the window is applied. - Once more than 100 events exist, a newly posted event appears in the browser timeline (both all-threads and single-thread views) and in the inbox panel.
agora inboxsendslatest=truein default,--open, and--allmodes. With more actionable items than--limit, it shows the newest ones and prints the note to stderr. With fewer, it prints no note.- In the reproduction above, the new instruction appears in the
agora inboxoutput and in thelatest=truetimeline response. - The README documents
latest. - Tests cover the store, server, and CLI behavior.
make verifypasses.
Reactions are currently unavailable
Activity
[-]Add GitHub Actions reporter example for PR and CI events[/-][+]Track inbox status per recipient for multi-agent events[/+][-]Track inbox status per recipient for multi-agent events[/-][+]Prevent bounded feeds from hiding new events[/+][-]Prevent bounded feeds from hiding new events[/-][+]Track targeted event status per recipient[/+][-]Track targeted event status per recipient[/-][+][agora-fake-strategist] Track targeted event status per recipient[/+][-][agora-fake-strategist] Track targeted event status per recipient[/-][+][agora-fake-strategist] Make JSONL replay survive large posts and interrupted appends[/+][-][agora-fake-strategist] Make JSONL replay survive large posts and interrupted appends[/-][+][agora-fake-strategist] Add latest-window reads so the timeline and inboxes keep showing new events[/+]