139: "Who can I ask?" — discover teammate agents by skill and engage them; publish cards for hosted personas#178
Draft
agent-relay-code[bot] wants to merge 9 commits into
Draft
Conversation
kjgbot
marked this pull request as draft
July 21, 2026 14:16
Contributor
|
End-to-end merge gate: this PR is not production-ready yet. Validated locally at
Real integration blockers:
Unblock/merge criteria:
Marking draft so the passing mocked checks cannot be mistaken for full ecosystem proof. |
…force-factory-49b6fd48
Member
|
Addressed the branch-integration finding from the merge-gate review on the current PR head.
The PR remains draft. The external merge gates are still blocked exactly as identified: Relaycast #294 is not deployed, Workforce #296 has not published |
added 6 commits
July 21, 2026 17:10
…force-factory-49b6fd48
…force-factory-49b6fd48
…force-factory-49b6fd48
6 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of the cross-repo epic #2785. This is the consumer issue — the one that makes the ecosystem come alive. Depends on the directory from relaycast#294 and the shared card contract from workforce#296.
Why
The Factory turns issues into reviewed PRs by spawning worker agents. Today, when a worker hits a question it can't answer, it has nowhere to turn — Factory only discovers fleet nodes/capabilities for placement (
FleetClient.roster()), not agents by skill, and there's no path to actually ask another agent. Once every proactive agent publishes an A2A card and registers with the Relaycast directory, a Factory worker should be able to: "who can answer X?" → pick an agent by its card skills → send it the question and get a reply.What
1. Directory-backed peer discovery
Add a card-aware lookup alongside
roster()inFleetClient(src/ports/fleet.ts), implemented inRelayFleetClient(src/fleet/relay-fleet-client.ts) — query Relaycast'sGET /v1/a2a/directoryfiltered by skill/tag, returning{ name, skills[], url, kind }per candidate. Optionally cache via an in-package index likeRelayflowPolicyRegistry(src/dispatch/relayflow-registry.ts).2. "Ask a teammate" capability
Give a running worker a way to engage a discovered peer: resolve target via #1, then send over Relaycast — A2A
POST /a2a/rpcmessage/sendor the broker seam (FleetClient.sendMessage/waitForInjected/onAgentMessage). Reuse the existing DM/relay path; don't invent a new transport. Surface it as a discrete capability/tool the worker invokes mid-task, with a bounded wait for the reply.3. Publish cards for factory-hosted personas
Generate an A2A card for factory-hosted personas (e.g.
.agentworkforce/agents/factory-feature-guardian/persona.json) via@agentworkforce/persona-kitderiveAgentCard([workforce#296]) and publish it when the persona-backed node comes online —createFactoryNodeDefinition(src/node/factory-node.ts) already assembles capabilities/tags/metadata and callsdefineNode. Export the new surface fromsrc/index.ts.Acceptance
FleetClientmethod returns teammate agents matching a skill/tag from the Relaycast directory (with how to reach each).deriveAgentCard-derived card when their node comes online; they appear in the directory.src/index.ts; card schema consumed from@relaycast/a2a(no hand-rolled shape).✅ End-to-end verification — Factory success criteria (REQUIRED)
This issue IS the "does the ecosystem come alive?" proof. "Compiles" is nowhere near done — the Factory must run a real discover → ask → reply round trip and observe the reply arrive, then check the harness in. Use
agent-relay's in-process broker so this runs locally with no external services (src/fleet/internal-fleet-client.ts,src/fleet/ensure-relay-broker.ts).Run it
The E2E (
test/e2e/ask-a-teammate.test.ts, runnable vianpm test) must:/v1/a2a/directoryHTTP response, or seed the in-process broker) with two agents whose cards declare distinct skills (e.g.["infra-watch"],["code-review"]).skill: "infra-watch"→ assert it returns only the infra agent, with an address to reach it.InternalFleetClient+ensureRelayBroker) that replies to an inbound question with a canned answer.createFactoryNodeDefinition, then assert itsderiveAgentCard-derived card was published/registered and shows up in the directory lookup from step 2.Observe (must pass)
[]for an unknown skill.Deliverable
test/e2e/ask-a-teammate.test.tsrunning the full discover→ask→reply round trip against the in-process broker + mock directory, one command (npm test).Anchor files
src/ports/fleet.ts(FleetClient,RosterEntry,sendMessage/waitForInjected/onAgentMessage)src/fleet/relay-fleet-client.ts,src/fleet/internal-fleet-client.ts,src/fleet/ensure-relay-broker.tssrc/dispatch/relayflow-registry.ts(in-package registry precedent)src/node/factory-node.ts(createFactoryNodeDefinition),src/index.ts(public barrel).agentworkforce/agents/factory-feature-guardian/persona.json(proto card / template)planning/linear-issue-cloud-proactive-runtime-fleet-unification.md,planning/factory-unified-node-architecture-linear-issue.mdFixes #139
Summary by cubic
Adds teammate discovery and an “ask a teammate” tool so workers can find agents by skill and get replies over the relay; also publishes A2A cards for factory-hosted personas so they appear in the Relaycast directory. Delivers the discover → ask → reply flow and shared card publishing required by issue 139.
New Features
FleetClient.discoverTeammates(TeammateQuery)viaRelaycastTeammateDirectory(GET /v1/a2a/directorywithskill/tag/q). Enforces exact skill/tag matches client-side, dedupes by kind+address, preserves server alias matches forq, and times out cleanly. Works inRelayFleetClient(workspace key or agent token;directoryFetch/directoryTimeoutMs/teammateDirectory) andInternalFleetClient(inject aTeammateDirectoryor use a workspace key). Unit tests cover filtering and free-text queries; E2E attest/e2e/ask-a-teammate.test.tsasserts client-side filtering even if the server returns all rows.askTeammate(fleet, { from, question, ... })resolves a target, arms the listener before send, accepts only that agent’s reply addressed to the requester, useswaitForInjectedwhen available, and fails with a bounded timeout.@agentworkforce/persona-kit(compat mapper aligned with upstreamderiveAgentCard: intent fallback when no skills, non-transport capabilities mapped to skills e.g.pullRequest→review, transport capsstreaming/pushNotificationsset), validate with@relaycast/a2a; publish viaRelaycastAgentCardPublisher(POST /v1/a2a/register). On 409, verify an exact card match withGET /v1/a2a/agentsand returnalreadyPublished(pluscertificationwhen present).createFactoryNodeDefinition(...)attachesagentCard;startFactoryNode(...)publishes on node-online and exposes acardPublishedpromise.TeammateQuery,TeammateAgent,RelaycastTeammateDirectory,askTeammate), persona tooling (deriveFactoryPersonaCard,RelaycastAgentCardPublisher,startFactoryNode), and defaults (DEFAULT_RELAYCAST_BASE_URL,DEFAULT_TEAMMATE_DIRECTORY_TIMEOUT_MS,DEFAULT_ASK_TEAMMATE_TIMEOUT_MS). AddsA2aSkillto types. Tests include unit coverage plus an end-to-end round trip. Persona update:.agentworkforce/agents/factory-feature-guardian/persona.jsonaddsskillsandrelay.agentName.Migration
fleet.discoverTeammates({ skill | tag | q })oraskTeammate(...)to consult a peer mid-task.RelayFleetClient, configure a workspace key or agent token; inInternalFleetClient, pass ateammateDirectoryor a workspace key.personatocreateFactoryNodeDefinition(...)and provide aRelaycastAgentCardPublishertostartFactoryNode(...)when anagentCardis present.Written for commit d93aaa5. Summary will update on new commits.