Documentation
¶
Overview ¶
Package peer implements the `call_peer` built-in tool: named delegation from one core-agent daemon to another over attach-mode HTTP. It is Gap 2 of docs/kube-agents-platform-fit.md — the piece a fleet parent needs to route "what's going on in cluster prod-1?" to the operator agent that actually lives in prod-1.
Three properties the package holds by construction, because the alternative is a tool whose docs claim more than the code enforces:
- No arbitrary-URL parameter. The model names a PEER; the endpoint comes from the hub's own registry, which only accepts absolute http(s) URLs (attach.validatePeerEndpoint) from an authenticated registrant. An unknown name is refused, not dialed. Same anti-SSRF shape as the alert tool.
- No credentials in the schema. The bearer token presented to the peer is read from the operator-named env var at call time, so it never appears in the tool's arguments, the audit log, or the model's context.
- Bounded. Every call gets a wall-clock deadline and a response byte cap; a peer that never finishes its turn fails the call instead of pinning the parent's turn open.
Each call runs in a FRESH session on the peer (POST /sessions), so two concurrent callers can't interleave prompts into one transcript and the turn boundary we wait on is unambiguously ours. That makes the peer's attach.multi_session a hard requirement — see New.
Index ¶
Constants ¶
const ( // DefaultToolName is the tool's name unless the operator renames it // via tools.call_peer.name. DefaultToolName = "call_peer" // DefaultTimeout bounds one delegated call end to end: session // creation, inject, and the wait for the peer's turn to complete. // Generous because the callee is a full agent turn (tool calls // included), not an HTTP echo. DefaultTimeout = 120 * time.Second // MaxTimeout is the ceiling config may raise the deadline to. A // call_peer that can outlive a Kubernetes liveness probe is a // wedged parent, not a patient one. MaxTimeout = 15 * time.Minute // DefaultMaxResponseBytes caps how much of the peer's answer enters // the parent's context. Over the cap the answer is cut and the // result is flagged Truncated — the operator can read the rest in // the peer's own session, whose ID the result carries. DefaultMaxResponseBytes = 16 * 1024 )
Variables ¶
This section is empty.
Functions ¶
func New ¶
New builds the call_peer tool. The caller (cmd/core-agent) invokes this only when tools.call_peer.enabled is set AND the daemon is running as a peer hub, so a registered call_peer always has a registry behind it.
dir supplies the live roster and must be non-nil. Callers that build the directory over a registry constructed later in boot should pass a DirectoryFunc closure rather than a nil Directory.
Types ¶
type Args ¶
type Args struct {
Peer string `` /* 164-byte string literal not displayed */
Prompt string `` /* 184-byte string literal not displayed */
}
Args is the tool's input. There is no endpoint, header, or timeout parameter: everything that decides WHERE the call goes and WHAT credentials it carries is operator configuration.
type Directory ¶
type Directory interface {
Peers() []Peer
}
Directory is the live roster of callable peers. Implemented over the hub's *attach.PeerRegistry by the wiring layer (pkg/compose); the tool takes the interface so it never reaches into registry internals and so tests can hand it a fixed roster.
Peers is consulted per call, not cached: registrations come and go on a lease, and a call to a peer that let its lease lapse should fail as unknown rather than dial a dead pod.
type DirectoryFunc ¶
type DirectoryFunc func() []Peer
DirectoryFunc adapts a plain function to Directory.
type Peer ¶
Peer is one callable destination: the subset of attach.Peer this package needs. Deliberately not attach.Peer — the tool has no business seeing registration IDs or hub-side ownership.
type Result ¶
type Result struct {
Peer string `json:"peer"`
// SessionID is the session the prompt ran in ON THE PEER. Surfaced
// so an operator can attach to it and read the full transcript when
// the summary here isn't enough (and it's the only handle they get
// when Truncated is true).
SessionID string `json:"session_id"`
Response string `json:"response"`
DurationMs int64 `json:"duration_ms"`
// Truncated reports that the peer's answer exceeded the response
// cap and Response holds only its leading bytes.
Truncated bool `json:"truncated,omitempty"`
}
Result is the tool's output.