Skip to content

Conversation

@vigoo
Copy link
Contributor

@vigoo vigoo commented Nov 17, 2025

Resolves #2286

Implements support for phantom agents, identified by a UUID as part of the agent ID.

The phantom-id when presetn is part of the agent-id, with a agent-type(params)[uuid] syntax. If not set, the agent-ids are just like before.

In the agent SDKs a new RPC client constructor is now available, called phantom, taking an optional phantom ID:

TypeScript:

const client = MyAgentClient.newPhantom(arg1, arg2);
// or
const client = MyAgentClient.getPhantom(phantomId, arg1, arg2);

Rust:

let client = MyAgentClient::new_phantom(arg1, arg2);
// or
let client = MyAgentClient::get_phantom(Uuid::new_v4(), arg1, arg2);

The fork host function has been changed so it no longer receives a name parameter, but always creates a new phantom agent with the same agent type and parameters but a newly generated ID. The forked agent's phantom ID is returned as part of the fork result.

NOTE
The original plan was that if an invocation targets an agent that is ephemeral and no phantom ID is set, we automatically generate one.
I did not implement this, because it's not straightforward to do it without significant performance loss, so I propose to revisit it after atomic deployment is merged, in 1.4.
The primary problem is:

  • Assigning a phantom ID to the invocation changes the agent ID, which means it now refers to a different entity. As shards are computed from the agent id, it can be assigned to a different worker executor so this association has to be done on the worker service level.
  • In the worker service we currently don't (cannot) have a cached "latest metadata of a component" information, we can only cache metadata for specific component versions (as they are immutable). To know whether we need to associate a random phantom ID, we would need to know if the agent is ephemeral, for which we need its agent metadata (part of the component metadata). If it would be an ephemeral agent, we would set a random phantom ID, which means we create a new agent, which uses the latest metadata - so we must use the latest metadata for this decision (and even then there would be a race condition here which probably is not a big issue in this case).
  • So because of the above, for every invocation that has no phantom id set (which is unfortunately the most common path) we would need to fetch (even if cached with some small ttl) the latest metadata for the component just to decide whether to assign a random phantom-id or not.

I did not want to do the above, so right now it's the user's responsibility to "correctly" use ephemeral agents - always generate a random phantom ID for them:

  • invocation APIs and CLI: it just have to be part of the agent-id with the new syntax
  • RPC: using the new phantom client constructors, without explicitly setting a phantom-id, will always generate a fresh one
  • Rib: this is something not implemented in this PR, will create a follow-up ticket because we need to figure out how to do it
    • RIB NOTE: we could also say we don't want any specific support for creating phantom agents from Rib, but instead do the "ephemeral agents are automatically getting a new phantom ID" in Rib only. There it has no performance penalty, because Rib works with specific component versions at the moment (and have it's metadata cached)

@vigoo vigoo changed the title Phantom ID support in AgentID, changed host interfaces Phantom agents Nov 17, 2025
@vigoo vigoo marked this pull request as ready for review November 19, 2025 18:50
@vigoo vigoo enabled auto-merge (squash) November 19, 2025 19:05
@vigoo vigoo merged commit 924c6dc into main Nov 20, 2025
47 of 48 checks passed
@vigoo vigoo deleted the phantom-agents branch November 20, 2025 15:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Phantom agents

3 participants