host.agents
host.agents resolves a handle to a connected agent so your app can talk to it: stream a conversation, read chat history, or read and (owner-only) narrowly update its config. An app only ever reaches agents it was granted at install. Grants are set server-side, never by the sandboxed app, so host.agents reflects the grant and never enumerates the platform.
host.agents is typed sugar over the generic resource factory host.get('agent', id); see host.rpc for the underlying get / list.
API
interface AgentsNamespace {
get(id: string): Promise<AgentHandle>;
list(): Promise<ResourceRef[]>; // granted agents only
}
interface AgentHandle {
id: string;
kind: 'agent';
uamp: AgentUampNamespace;
chats: AgentChatsNamespace;
config: AgentConfigNamespace;
capabilities(): Promise<AgentCapabilities>;
onDelta(cb: (event: unknown) => void): () => void; // streamed response.delta events
onMessage(cb: (event: unknown) => void): () => void; // message.created / message.updated
onPresent(cb: (present: unknown) => void): () => void; // agent present payloads
}List granted agents
await host.ready();
const granted = await host.agents.list();
// → ResourceRef[]: [{ kind: 'agent', id, scope? }, ...]list() returns only what this app instance was granted. An empty array means no agent is connected.
Resolve a handle and stream a turn
const agent = await host.agents.get(granted[0].id);
const caps = await agent.capabilities();
// → { mode, input, output, execution, displayName?, username?, voiceId?, ... }
renderHeader(`@${caps.username ?? caps.displayName}`);
await agent.uamp.turn('Summarize the open document.', {
onDelta: (delta) => appendDelta(delta),
onDone: () => markComplete(),
});agent.uamp is the realtime UAMP bus:
turn(content, opts?): send one text or multimodal turn and stream the reply (onDelta,onDone).send(event): send a raw UAMP event or batch.on(cb): listen to streamedresponse.deltaevents; returns an unsubscribe.
Chat history
const chats = await agent.chats.list();
const recent = await agent.chats.get(chatId, { limit: 50 });
await agent.chats.send(chatId, 'A follow-up question.');
const off = agent.chats.subscribe(chatId, (event) => handle(event));Config (read, owner-only write)
const cfg = await agent.config.get();
// Owner only; the server enforces a narrow allowlist (ui / greeting / ...).
await agent.config.update({ greeting: 'Hi, I help with hardware design.' });config.update is owner-only and the server restricts it to a narrow allowlist of non-secret fields. Attempts outside the allowlist, or from a non-owner, are rejected.
Event streams
A handle exposes three event subscriptions, each returning an unsubscribe:
onDelta(cb): streamedresponse.deltaevents.onMessage(cb):message.created/message.updatedevents.onPresent(cb): agentpresentpayloads (filtered out of the delta stream).
Notes
- Reaching an agent the app was not granted rejects (the bridge gates the
(kind, id)). The grant is a defense-in-depth filter; the underlying routes still authorize the viewer independently. See the security model. - To find an agent to connect to in the first place, use host.discover.
Related
- host.discover: find agents to connect to
- host.fn: call a granted agent's server endpoint directly
- host.rpc: the generic
host.get/host.listfactory - Protocols: UAMP, the agent messaging protocol behind
uamp