Repository navigation
Let the lookout hear sources the person sets up outside the daemon - #305
Conversation
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
Security findingsAdvisory findings (1)ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a18799ecdc
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d4c6a8ceb2
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
53d41bc to
a9457ef
Compare
There was a problem hiding this comment.
🛡️ Codex Security Review · Automatically triggered
Here are some automated security review suggestions for this pull request.
Reviewed commit: a9457efacb
ℹ️ About Codex security reviews in GitHub
This is an experimental Codex feature. Security reviews are triggered when:
- You comment "@codex security review"
- A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review
Once complete, Codex will leave suggestions, or a comment if no findings are found.
A source is a command under [sonny.sources.NAME] in ~/.agent/config.toml that Sonny's lookout runs; each line it prints is an event (plain text or JSON with text, id, from, url, urgent). Agents subscribe by name with a subscription's new sources field and never define commands. Every event is told, unjudged, in a 'From your sources' note with the origin lookout.sources, so the approver never reads it as the person's words; an event the command marks urgent steers a busy subscriber. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jkdGCueMjCVQsvkY7iTCR
Each event gets a sequence number in its note's key, so urgent events read in the same millisecond are never one idempotent submit. A note stops at 128 KiB of rendered lines, and from/url are cut at 300 characters. every parses its unit by suffix, so a multibyte one is refused, not a panic. stderr is read with the same bounded line reader as stdout. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jkdGCueMjCVQsvkY7iTCR
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jkdGCueMjCVQsvkY7iTCR
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jkdGCueMjCVQsvkY7iTCR
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jkdGCueMjCVQsvkY7iTCR
Main's restamp still called Places::plist, which #344 renamed to job; sonny no longer built. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jkdGCueMjCVQsvkY7iTCR
a9457ef to
22e7e90
Compare
#305's sources carry over as they are: a subscription's sources field, the runner, and the From your sources note with its origin. With no judge left, a subscription may name sources beside bots, and a sources note waits only for the subscriber to rest. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013BJVqR47cCbbWHuxEdaCJD
Requested by George · project thread
Opens Sonny's lookout to external services: you write a poller (for example for Slack), and the lookout passes what it prints to the agents that subscribed. The daemon and the
agentCLI don't change.What it does
~/.agent/config.toml:sh -c, in its own process group, withSONNY_SOURCEandSONNY_SOURCE_DIR(STORE.sources/NAME, where the poller can keep its cursor). Each printed line is one event. It can be plain text, or JSON withtextand optionallyid,from,urlandurgent. A poller that exits runs again afterevery, and a stream that never exits works too. Anidseen lately counts as news only once. The settings are re-read every 15 s, and a stopping lookout stops its commands.sources: [...]field on a subscription. An unknown name is refused, and the tool result lists the sources that exist. Agents can never define a command, so a sandboxed bot can't use the lookout to run one."urgent": truesteers a busy subscriber, and the rest wait until it rests.look_foralongsidesourcesis refused. Events still waiting follow subscription changes: a source no longer subscribed to is dropped.From your sources:that quotes each event's text as a JSON string. It goes out with originlookout.sources, so the approver never reads Slack text as George's words. Its request id islookout-*, so it stays quiet in Sonny and shows folded as↳ From your sources · slack 2./backgroundlists the subscription assource slack · every event.Code:
sonny/src/lookout/sources.rs(new runner and note), additive hooks inlookout/mod.rs, plussubs.rs,served.rs,transcript.rsandclient/src/config.rs(beside[sonny.mcp_servers]). Docs: a new "Sources" section indocs/LOOKOUT.mdand a row insonny/README.md.Also carries a one-line fix for main's build:
trigger::restamp(#318) still calledPlaces::plist, which #344 renamed tojob.Codex's security note on outside text reaching a tool-enabled turn is logged as #348.
Screenshots
Captured from a live run: a real daemon, Sonny and lookout, a scripted model, and a poller printing a lunch message plus an urgent failed deploy.
Tests
every, line parsing, id dedupe, the runner running a real command twice with its state folder, the note, subscription matching and re-matching, andwake_sourcesagainst a stand-in daemon (origin, queue vs steer, byte budget).test_what_a_source_prints_reaches_who_subscribed_to_it. After rebasing on main,AGENT_TEST_RUNTIME=1 python3 -m unittest tests.test_lookout tests.test_servedpasses, 20 tests.cargo test -p sonny -p agent-clientpasses.Follow-ups not done: showing each source's last run in
/background, and keeping seen ids across lookout restarts.🤖 Generated with Claude Code
https://claude.ai/code/session_013jkdGCueMjCVQsvkY7iTCR