Skip to content

Add cross-agent-handoff example (shared session across agents) - #387

Open
HarshaNalluru wants to merge 3 commits into
mainfrom
add-cross-agent-handoff-example
Open

Add cross-agent-handoff example (shared session across agents)#387
HarshaNalluru wants to merge 3 commits into
mainfrom
add-cross-agent-handoff-example

Conversation

@HarshaNalluru

Copy link
Copy Markdown
Contributor

What

A small, runnable example under moss-live-labs/examples/cross-agent-handoff that moves a conversation between agents without the customer repeating themselves, using one shared Moss session.

The idea

Each agent keeps its own private context, so a handoff (chat to voice, bot to human, phone to laptop) usually resets to zero. Instead, all agents share one named session. Agent A writes the conversation and pushes it; Agent B opens the same session by name, resumes it (no re-embedding), and queries context it never directly received.

# --- agent A (chat) ---
session = await moss.session(index_name="call-8821")
await session.add_docs([...])            # the conversation turns
await session.push_index()               # hand off to the cloud

# --- agent B (voice, different client) ---
session = await moss.session(index_name="call-8821")   # same name -> resumes
ctx = await session.query("was a refund promised?", QueryOptions(top_k=1))

Contents

  • cross_agent_handoff.py — simulates two independent agents in one process: A pushes a session, B (a fresh client) resumes it and answers about the charge, the refund, and the order number, none of which it was told directly
  • README.md, .env.example, .python-version, pyproject.toml, uv.lock

Run

uv sync && cp .env.example .env   # Moss keys
uv run python cross_agent_handoff.py

Notes

  • Mirrors the structure and API of the existing semantic-cache example (moss.session(index_name=...), add_docs, push_index, query).
  • Draft: syntax-checked and uv lock resolves, but I have not run it against a live Moss project in this environment (no credentials here). Worth a quick uv run before merge to confirm B sees A's pushed context.

Copilot AI review requested due to automatic review settings July 13, 2026 22:24

# unique per run so the demo starts clean; in production use a stable id such
# as the call / conversation id so the same session is resumable later.
session_name = f"call-handoff-demo-{uuid.uuid4().hex[:8]}"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CONSIDER session_name = f"call-handoff-demo-{uuid.uuid4().hex[:8]}"

Because this session is immediately push_index()ed, every run creates a new cloud index with a random name and no cleanup path. That can leak indexes/docs into a user's project just from trying the demo. Either use a stable demo name that is reused, or clean up in main() after the handoff completes, e.g. try: ... finally: await _client().delete_index(session_name).

@github-actions

Copy link
Copy Markdown

Codex review

The new live-labs handoff example is straightforward and mostly follows the existing session pattern. The main concern is that the runnable demo leaves persistent cloud state behind on every execution.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new experimental runnable Python example under moss-live-labs/ demonstrating cross-agent handoff by having multiple agents share a single named Moss session (agent A writes + pushes; agent B resumes and queries).

Changes:

  • Introduces a new cross-agent-handoff example script that simulates two independent agents using the same session name.
  • Adds minimal project scaffolding for running the example via uv (pyproject, lockfile, env template, python version pin).
  • Documents the concept and run instructions in a new README.

Reviewed changes

Copilot reviewed 5 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
moss-live-labs/examples/cross-agent-handoff/cross_agent_handoff.py New runnable example simulating agent A session push and agent B resume/query flow.
moss-live-labs/examples/cross-agent-handoff/README.md Explains the handoff concept and how to run the demo.
moss-live-labs/examples/cross-agent-handoff/pyproject.toml Defines a small uv project with moss + python-dotenv dependencies.
moss-live-labs/examples/cross-agent-handoff/uv.lock Pins resolved dependencies for reproducible installs.
moss-live-labs/examples/cross-agent-handoff/.env.example Template for required Moss credentials.
moss-live-labs/examples/cross-agent-handoff/.python-version Pins the example’s Python version to 3.12.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +55 to +57
## Resources

- [Docs](https://docs.moss.dev/docs/build/cross-agent-handoff)
Comment on lines +24 to +28
def _client() -> MossClient:
return MossClient(
project_id=os.environ["MOSS_PROJECT_ID"],
project_key=os.environ["MOSS_PROJECT_KEY"],
)
@HarshaNalluru
HarshaNalluru marked this pull request as ready for review July 14, 2026 19:40
@HarshaNalluru
HarshaNalluru requested a review from r4ghu as a code owner July 14, 2026 19:40
Copilot AI review requested due to automatic review settings July 14, 2026 21:05
@HarshaNalluru

Copy link
Copy Markdown
Contributor Author

Addressed the review:

  • Demo cleanup: main() now wraps the handoff in try/finally and calls delete_index(session_name), so a demo run no longer leaves a random cloud index behind.
  • Fail-fast creds: _client() reads MOSS_PROJECT_ID/MOSS_PROJECT_KEY via a _require() helper (os.getenv + clear exit message) instead of os.environ[...], so missing creds fail cleanly even if the helpers are called directly.
  • Docs link: README now points to the root https://docs.moss.dev (with UTM), matching the other examples.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 6 changed files in this pull request and generated 2 comments.

Comment on lines +50 to +52
# hand off: persist the session so any other agent can resume it
await session.push_index()
print("[agent A - chat] wrote 3 turns and pushed the session to the cloud\n")
Comment on lines +14 to +17
The first agent opens a session by name, writes the conversation, and pushes it
to the cloud. The second agent, a different process or device, opens the *same*
session name. Because that index already exists, Moss resumes it (no
re-embedding), and the agent can query context it never directly received:
@HarshaNalluru

Copy link
Copy Markdown
Contributor Author

Addressed the latest review:

  • Deterministic handoff: agent_a_handles_chat now captures the push_index() result and await moss.wait_for_job(result.job_id) before agent B resumes, so the cloud index is fully ready to auto-load (no race).
  • README: updated the snippet to wait_for_job(result.job_id) after push_index(), plus a note that push_index() queues server-side processing and you should wait (or poll get_job_status) before another agent resumes.

Copilot AI review requested due to automatic review settings July 15, 2026 02:19

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 6 changed files in this pull request and generated 4 comments.

Comment on lines +50 to +55
# hand off: push to the cloud. push_index() queues a server-side indexing job,
# so wait for it to finish before another agent tries to resume the session.
result = await session.push_index()
if result.job_id:
await moss.wait_for_job(result.job_id)
print("[agent A - chat] wrote 3 turns and pushed the session to the cloud\n")
Comment on lines +91 to +95
finally:
# demo cleanup: this run pushed a cloud index, so remove it. In production
# you would keep the session (a stable, resumable id) instead of deleting it.
await _client().delete_index(session_name)
print(f"\ncleaned up demo session: {session_name}")
Comment on lines +26 to +28
result = await session.push_index() # queues a cloud indexing job
await moss.wait_for_job(result.job_id) # wait until it's ready to resume

Comment on lines +35 to +38
`push_index()` doesn't finish instantly: it queues server-side processing and
returns a `job_id`. Wait for that job (`wait_for_job`, or poll `get_job_status`)
before another agent resumes the session, otherwise the index may not be ready
to auto-load yet.
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.

2 participants