Skip to content

Give a duplicated coworker the endpoint it was copied from - #328

Open
zopeVaibhav wants to merge 1 commit into
CopilotKit:mainfrom
zopeVaibhav:fix/duplicate-repoints-the-copy-at-the-managed-bot
Open

Give a duplicated coworker the endpoint it was copied from#328
zopeVaibhav wants to merge 1 commit into
CopilotKit:mainfrom
zopeVaibhav:fix/duplicate-repoints-the-copy-at-the-managed-bot

Conversation

@zopeVaibhav

Copy link
Copy Markdown
Contributor

Closes #327.

What this changes

Duplicating a coworker now gives back a copy that runs where the original ran.

duplicate() wrote the managed Bot's address into every copy without reading the source, so duplicating a coworker hosted at its own AG-UI endpoint produced one answering from a different process under the same name, title and role. The copy's builtIn flipped to true as a result, and the connection section hides the endpoint entirely once that is set, so the swap was invisible on the one screen somebody would check.

The managed address is the fallback create() already applies to a coworker given no endpoint. This makes duplicate() treat it the same way rather than as a rule, which fixes three things at once:

  • A copy of a coworker with its own endpoint keeps that endpoint.
  • A copy of an endpoint-less coworker still runs on the managed Bot, as its source did.
  • Duplicate works on a deployment with no managed Bot when the source brought its own endpoint. It refused there before, telling the person to give the coworker an endpoint it already had.

The endpoint alone is inherited, never the rest of the configuration. auth is a reference into the vault, so copying it would leave two coworkers sharing one credential, where rotating either one's key silently changes the other's. A copy starts with no key and fails closed at its endpoint until somebody gives it one.

Not changed here: avatarSeed is copied from the source and is pinned by an existing test, so a copy still renders the source's avatar. That is worth deciding on its own rather than inside this change.

Where it runs

  • New state that outlives a request? None. One INSERT gains a value read from the row being copied, inside the transaction that already reads it.
  • What happens on the second replica? No change. duplicate() reads its source and writes its copy in one transaction, and the value it now writes comes from that transaction's own read rather than from process configuration. Two replicas duplicating the same source produce two copies with distinct minted ids, exactly as before.
  • Anything serialised? Nothing new. The existing transaction is unchanged, and the added read is of the row it already selected.
  • Anything fanned out to a browser? No. The agent list is refetched by the client after a create or duplicate as it was.
  • New listener, port, or schedule? None.

Boundary and audit

  • Every acting call still goes through the gateway: unchanged, no acting call is added or moved.
  • New refusals and new failures each write a row: no new refusal is introduced. ManagedAgentUnavailableError still fires, on a strictly smaller set of cases (no managed Bot and no endpoint on the source), and is mapped by the same mapStoreError path as before.
  • Nothing new is trusted from the client that the server can resolve itself: the endpoint is read from the stored source row, not accepted from the request.

Changelog

  • Added under Unreleased.

Proof

Five tests added to server/tests/agent-profile-store.integration.test.ts, which exercises the real store against Postgres.

Run against the unfixed code first, two fail and three pass. The two that fail are the proof; the three that pass pin behaviour this change must not break.

(fail) copies the source's own endpoint rather than repointing the copy at the managed Bot
  Expected: "https://hosted.example.test/ag-ui"
  Received: "https://managed.example.test/ag-ui"

(fail) duplicates a coworker with its own endpoint on a deployment with no managed Bot
  ManagedAgentUnavailableError: This deployment has no managed Bot. Give the coworker its own AG-UI endpoint.

 18 pass, 2 fail

After the change:

 20 pass, 0 fail

The three that passed both before and after:

  • an endpoint-less source still gets the managed Bot,
  • the source's stored key is not carried onto the copy (asserted on the copy's hasAuth and on authFromConfiguration over its stored row),
  • duplicate still refuses when there is no managed Bot and no endpoint on the source to inherit.

Verified end to end against a running server as well, not only in tests. A coworker created at http://localhost:4201/ag-ui duplicates to a copy at http://localhost:4201/ag-ui with builtIn: false; an endpoint-less coworker duplicates to the managed address with builtIn: true; and a second server started with both MANAGED_AGENT_* variables unset returns 201 for the first case where it returned 400 before.

Full server suite run with the local dev server and worker stopped, since they contend on the same database and make the lease tests flap. The set of failing tests is identical with and without this change (six, all pre-existing, in routine-sweep.integration.test.ts and agent-handoff-*.integration.test.ts); compared by test name rather than by count. typecheck, lint and format are clean.

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.

Duplicating a coworker gives back a copy that runs somewhere else

1 participant