Skip to content

We need an "Agent View" for remote agents #3996

Open

Description

@gdotbat

Is your feature request related to a problem? Please describe.

Buzz already supports running agents as headless buzz-acp bridges — a great fit
for always-on agents backed by runtimes like Hermes or OpenClaw, hosted
on a workstation/server and connected to a community relay 24/7, independent of
any desktop client.

The problem: the desktop Agents view only lists agents the local app
manages/hosts itself (AgentsView → UnifiedAgentsSection). Externally-hosted
bridge agents never appear there. They only surface as channel members (their
kind:10100 profile badges them as "agent" in member lists and @mention
autocomplete), but there is no representation in the Agents area itself.

This forces a bad tradeoff:

  • To see/manage an agent in the Agents area, the desktop app has to host it —
    which ties the agent's lifetime to that app instance being open, so true 24/7
    operation is impossible (close the app → the agent goes offline).
  • Hosting the same agent on more than one device conflicts (two harnesses on
    one identity, racing on the relay).
  • So anyone running Hermes/OpenClaw agents as always-on bridges has no
    first-class, at-a-glance Agents surface
    for them — only a per-channel member
    popup.

Describe the solution you'd like

  1. A read-only "Community / External agents" section in the Agents view that
    lists agents present in the community via their kind:10100 agent profile
    (+ kind:0), regardless of which device or process hosts them — including
    bridge agents the local app does not manage.
  2. Clear separation of "Managed here" vs "External". Externally-hosted agents
    get view/interact affordances (open profile, DM, @mention, online/offline
    presence) but no start/stop/edit/delete controls, since the local app
    doesn't own their runtime — and no "Configuration missing" / "Stopped" states
    for agents the app was never hosting.
  3. A uniform way to register/label an externally-hosted agent into the
    community's Agents roster from any device
    — publish/curate its agent profile
    (name, avatar, description) without the app taking over hosting — so multiple
    people can each stand up their own always-on agents on their own machines and
    have them all appear consistently in everyone's Agents view for that community.

Describe alternatives you've considered

  • Hosting agents via the desktop app (managed): rejected — not 24/7 (the
    harness dies when the app closes), and hosting the same agent on multiple
    devices conflicts.
  • Publishing kind:10100 manually (e.g. via buzz channels set-add-policy):
    makes the agent show up in member lists / mentions, but not in the Agents
    view, and the profile content isn't a real agent profile. A workaround, not a
    surface.
  • Relying on the channel member popup only: fine for chatting, but there's no
    agent-overview surface and it doesn't scale across many agents and devices.

Additional context

Concrete setup this would serve: a Mac hosts Agent1/Agent2/Agent3 as
buzz-acp → hermes -p <profile> launchd bridges on a shared community relay; a
Windows box and a Raspberry Pi host their own agents the same way. All of them
should appear in every device's Agents view as community agents — hosted only
where their bridge runs, viewable and interactable everywhere, start/stop-able
nowhere but their host.

This mirrors how Discord shows bots in a server: the bot runs server-side,
always-on, and every client sees and can interact with it regardless of which
client is open — no client "hosts" the bot.

Activity

  1. UNST-ai commented on Aug 1, 2026

    @UNST-ai

    +1 for this one.

  2. murdawkmedia commented on Aug 1, 2026

    @murdawkmedia

    I validated this request against a real mixed-harness deployment: two independently hosted Hermes residents and two OpenClaw residents spread across Windows, Linux, and macOS, each with its own signing identity, runtime, state, and credentials, all using one authenticated community relay. They already produce canonical signed replies and remain available independently of Desktop, but—as this issue describes—channel membership does not project them into the Agents view.

    I also composed the reviewed heads of #4006, #4023, and #3964 against current main in an isolated branch. They merge cleanly and are complementary, but do not yet compose into this issue's end state. #4006 has since gained an unrelated initial-window helper extraction; its connected-agent code is unchanged.

    • feat(desktop): connect self-hosted agents #4006 is a useful local pointer in the key-custody/lifecycle sense: it stores a public key, local label, and SSH alias separately from managed agents, with no secret key, process command, PID, autostart, or local Start/Stop/Delete semantics. However, it is local-only and SSH-required. Reachability plus an observed binary does not cryptographically bind that host to the supplied agent pubkey, so I would describe this as an optional endpoint bookmark unless/until a signed challenge establishes the binding.
    • fix(desktop): make remotely hosted agents mentionable from other machines #4023 makes signed directory profiles useful for cross-machine mentions, but only publishes for locally managed agents and does not project relay-discovered agents into AgentsView. Its generated kind:10100 hardcodes status: "online" independently of runtime state and reconstructs the replaceable profile rather than preserving fields, so profile status should not be treated as presence and refreshes need one shared non-clobbering merge path.
    • feat(cli): add verified long-running client primitives #3964 supplies promising external-adapter primitives (users me, profile read-modify-write, scoped listen). A production resident loop still needs explicit Windows key-file ACL handling, independently verified signed stream records, paginated catch-up beyond the relay's 1,000-event page ceiling, and a profile surface for the mention-policy fields used by fix(desktop): make remotely hosted agents mentionable from other machines #4023 (respond_to, allowlist, and current channel IDs). Reconnect remains at-least-once, so adapters must deduplicate by event ID.

    The model that fits this deployment cleanly would be:

    1. Community roster projection: signed kind:10100 + kind:0, intersected/annotated with current community/channel membership, deduplicated by pubkey.
    2. Separate optional endpoint annotations: SSH host or other management endpoint is local metadata, not identity truth, and must not be required merely to display a resident.
    3. Runtime-backed presence: derive online/offline from presence/heartbeat facts, not a static profile field.
    4. One shared profile merge path: every publisher preserves fields it does not own, including channel-add policy and future extensions.
    5. Strict lifecycle boundary: external cards have profile/DM/mention/navigation affordances but never import keys or expose local Start/Stop/Edit/Delete controls.
    6. Truthful labels: signed profile name/avatar remain canonical; a user-supplied local nickname or observed harness/location is displayed separately as an annotation.
    7. Verifiable adapter stream: preserve verified signatures and provide paginated catch-up so a long-offline resident can recover without silent gaps.

    This keeps the useful local-shortcut work in #4006, the cross-machine mention work in #4023, and the external CLI foundation in #3964 without conflating room membership, identity ownership, process custody, endpoint reachability, or conversational presence.

  3. svenrawr-stock-well commented on Aug 3, 2026

    @svenrawr-stock-well

    Additional source-level and prototype validation for this direction:

    At exact Desktop tag v0.5.2 / commit 3e48f1b2365d326ee1c9582448d86a99b44ecd5d, the gap extends beyond AgentsView into first-class mention eligibility:

    • desktop/src/features/messages/lib/useMentions.ts applies isAgentIdentityInManagedList(...) before accepting an agent mention candidate.
    • desktop/src/features/agents/lib/agentAutocompleteEligibility.ts accepts an agent identity only when its pubkey is in the Desktop-local managed set.
    • Relay profile and membership data cannot legitimately populate that lifecycle store.

    This creates a cross-client inconsistency: Mobile can mention an externally managed relay agent that Desktop omits. An honest relay-only workaround cannot fix unmodified Desktop without fabricating local ownership or misclassifying the identity.

    We built a non-deployed Desktop v0.5.2 prototype to test a stricter projection. It admits an external identity only when signed kind:10100 metadata, active viewer membership, authoritative bot role, advertised channel scope, and invocation policy agree. It keeps that identity outside managed persistence and every start/stop/edit/delete/configuration/reconciliation path, while enabling the existing pubkey for normal signed mentions and a read-only external-agent directory card.

    Validation completed:

    • full Desktop suite: 3,774 tests across 58 suites;
    • focused eligibility and managed-control tests;
    • typecheck plus frontend/E2E production builds;
    • Playwright directory, reload, and signed-mention cases;
    • focused Rust channel-projection test;
    • native Desktop build and an unsigned packaging checkpoint.

    The remaining design question is where Buzz wants the canonical authority contract resolved—relay/community API, shared client library, or per-client logic—and how replacement, freshness, revocation, archive/leave, and older-client behavior should work. We are intentionally holding the prototype rather than proposing code until maintainers confirm the preferred contract and implementation shape.

  4. mikececco commented on Aug 3, 2026

    @mikececco

    Opened #4537, which does the "derive online/offline from presence facts, not a static profile field" piece raised in this thread. It's only that piece — it deliberately doesn't touch the Agent View rendering, since several PRs are already in flight here and I didn't want to compete with them.

    The specific defect: agents_from_events (desktop/src-tauri/src/nostr_convert.rs) inserts status: "offline" whenever a kind:10100 profile carries no status string. Nothing in-tree ever writes that field — the only in-tree writer of kind:10100 is cmd_set_add_policy, which sets channel_add_policy — so the fallback is taken for every relay-discovered agent, and PulseView builds its status map straight off it.

    Meanwhile real presence already exists (kind:20001, 180s Redis TTL in buzz-pubsub/src/presence.rs, exposed client-side via usePresenceQuery). The two were never joined.

    #4537 joins them, preferring presence where it has an entry and falling back to the incoming status otherwise (so locally-managed agents keep their process-handle status, and there's no flicker before the query resolves).

    It should compose with whichever Agent View PR lands rather than conflict — the merge is a pure function in agents/lib/agentPresenceStatus.ts, reusable by the other roster surfaces (useMentions, useNewMessageRecipients, useTrayMenu).

  5. ezrahill commented on Aug 6, 2026

    @ezrahill

    +1 for this

  6. murdawkmedia commented on Oct 3, 2026

    @murdawkmedia

    Update to my August composition notes: #4006 has been closed, and #3964 was rewritten at 0ba5a866 to generic CLI commands. It now verifies event IDs/signatures and preserves signatures in stream output; the earlier profile writer is absent. My old composed-head checks therefore do not validate the current branches or Desktop roster/mention flow. #4537 remains open and covers presence status only. I have not retested current Desktop behavior.

  7. ngoclt commented on Oct 10, 2026

    @ngoclt

    +1 for this.
    Sometime the agents got stopped/stuck and there is no way for us to see what was happening.

  8. murdawkmedia commented on Oct 11, 2026

    @murdawkmedia

    Follow-up on the latest stopped/stuck-agent report, with current source and tests rather than my old August composition.

    At main 30873ba, externally hosted relay agents can now qualify for mentions through getMentionableAgentPubkeys and the ownership, invocation-policy and channel-membership rules. The earlier local-managed-only description is stale. In an isolated checkout using Node 24.15.0 and the existing test loader, the eligibility, active-turn store and working-signal test files passed all 131 checks. That includes same-owner agents across machines, channel admission, stale observer events and turn-liveness pruning. This was a focused source/test run, not a Desktop or deployed-fleet retest.

    The Agents view still feeds agents.managedAgents into UnifiedAgentsSection, so the read-only community roster requested here remains a separate gap. Current profile/card availability code already reads relay presence; Pulse's agentStatusMap still reads the profile-derived a.status. I also ran #4537's unchanged helper tests at 3f6a437: all six pass, but that PR handles presence display rather than stalled work or the external roster.

    For the stuck case, it would help to show presence and last observed work/liveness separately. An online bridge can have a stuck turn; expired or unavailable observer data should not imply successful completion. This also fits VISION_REMOTE_AGENTS.md: presence describes conversational availability, while unhealthy-substrate diagnostics remain host-owned. A roster should reuse the existing availability/observer signals without granting local lifecycle controls over external identities.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions