Why Coding Agents Are Moving from Sessions to Projects: A Handoff Case Study
This article explains why coding agents like GitHub Copilot and Cursor are adopting project-level context to persist goals, agreements, and progress across sessions, using a field migration example to demonstrate how agents can discover conventions, track task status, verify tests, and hand off work without human re-explanation.
Introduction
A colleague's agent is already modifying a feature, but your own agent doesn't know and duplicates the work. This information gap appears in team collaboration: developers track work with GitHub Issues and Cursor Projects, yet each person sees only their own agent and task board. What a teammate's agent is doing or what issues it discovered must be asked directly.
Even when you learn "someone is working on this," handoff requires confirming: how far the code has changed, whether tests passed, whether it's awaiting review or another person. The teammate must dig through chat sessions, share PR and test links, and note unfinished parts.
This mirrors everyday development: requirements live in documents, ad-hoc decisions in group chats, integration progress in someone's head. The new person reads docs and code but still finds mismatches, forcing them to ask the original developer: why was this kept, is that approach still happening? Both parties lose time waiting and recalling context.
With agents, a single developer may run multiple sessions simultaneously — one for backend, one for tests, another for client. Agreements confirmed in the backend session must be passed to the client; unfinished parts from the previous round must be handed over. The developer shuttles context and results across sessions.
A single piece of work spans multiple sessions. If each round requires a human to re-explain goals, progress, and agreements, the time saved by agent-written code is partly spent on handoff.
This is why coding agents are moving from Session to Project. Goals, progress, and agreements must persist outside sessions so subsequent agents can read and update them.
Session handles the immediate step; Project organizes the unfinished whole.
Recently, GitHub Copilot App's Projects entered public preview, and Cursor released a multiplayer Projects beta on November 11 (Beijing time). Both aim to connect cross-session work.
TL;DR
Sessions end, work doesn't. Project retains goals, tasks, and results so later sessions can continue without human re-explanation.
Handoff needs visibility into progress. Which agreement is valid, who is doing what, what has been tested — all must be queryable. Backend tests passing doesn't mean the client is done.
Try one handoff first. Use an existing Issue to link design docs, PRs, and CI; then start a new session and see if it finds the next step.
Finding the Right Convention
This migration renames nickname to display_name in user profiles. The backend agent has submitted code; the client-side colleague prepares their agent to continue.
The agent first locates the original requirement: "replace field name." However, during review the team changed direction. Legacy apps still read nickname, so the backend must return both fields until the old version retires.
If this decision exists only in the previous chat, a new agent seeing the old field might assume the previous agent didn't clean up. A human would ask in the group: "Why is the old field still there?" A knowledgeable colleague explains, and the agent needs that same context.
Feeding the entire chat to the agent forces it to distinguish proposals from final decisions. Simply saying "field migration complete" might mislead it into thinking the client is also done.
A clearly written convention solves this.
User profiles are gradually migrating to display_name . During migration, the backend returns both nickname and display_name with identical values for legacy app compatibility. The client will switch to reading the new field this round; old-field cleanup is tracked separately. This convention replaces the original requirement's "direct replacement" based on the reviewed interface contract.
The new agent reads this and understands the old field is intentionally retained ; its task is the client side.
In Copilot App, you can link backend and client repositories to the same Project, state the migration goal clearly, and place the reviewed interface contract in the Library. When assigning the client task, instruct the agent to follow that contract.
GitHub documentation emphasizes specifying which references to use when assigning tasks. Especially when old and new proposals coexist, merely adding files isn't enough — the agent must know which one to follow.
In Cursor's multiplayer Project, this convention can live in shared Context at /cursor/stores/self, readable and writable by all project members' agents, synced to cloud and local environments. A different agent picking up the work can still find it.
Which version is current and which is obsolete must still be documented explicitly.
Picking Up Unfinished Tasks
With the convention found, the next step is clarifying progress. "Done" from the backend could mean code written, PR opened, merged, or tests passed. The client might not have started, or a colleague may have already launched an agent for it — invisibly.
In Copilot's Overview, you can filter by status: open PRs appear under Open with linked sessions and PRs; items awaiting confirmation appear under Needs input. Drill into a session to see plans, changes, and discussions.
Thus the client-side colleague doesn't rely on a vague "done." Backend progress is traceable via PRs; client reading changes and old-field cleanup remain as unfinished work in the project.
In Cursor, handoff clues live on project tasks. Per the October official update, each task has an ID, status, executing agent, and linked PR, updated by the Coordinator and viewable on a board.
In the multiplayer version, each teammate has their own Coordinator (plans work) and Worker (executes tasks), sharing a single task board. A client-side colleague entering from their chat can see how far the migration has progressed.
If a task only says "backend tested" without a test link, the client's Coordinator can ask the backend colleague's Coordinator. Cursor spawns a side conversation from the other's chat to answer, marking sender identity. That side conversation can read the task board but not modify it — asking for background won't accidentally alter the other task's progress.
Previously this step relied on a colleague forwarding links and explaining "look at this PR, tests are here." Now agents can follow task records themselves, asking only for missing pieces.
Who is doing what, how far, and where the results are — all queryable from a single task.
Seeing What Was Tested
Assume the backend leaves this record:
Backend PR #84, commit a1b2c3d . CI #315 interface tests passed. Response contains both nickname and display_name with identical values.
This record confirms the backend version returns both fields per the convention. Which field the client reads must be checked in client code.
The receiving agent traces the client code and finds the UI still uses nickname. The task is clear: change the reading logic and add a test verifying it reads display_name.
There's a subtle pitfall. Since both fields hold the same value in normal responses, the client reading the old field still displays correctly.
Only checking "name displays correctly" may never reveal whether the client was actually updated.
A small guard in the client unit test can catch this: set nickname to "old nickname" and display_name to "new display name", then assert the page shows "new display name". If code still reads the old field, the test fails.
These differing values are deliberately crafted test data to verify which field the client selects. The real backend continues returning identical values per the contract.
After the client agent finishes, it attaches its PR, commit, and test results to the task. The next person can distinguish: backend tested dual-field return; client tested reading the new field.
These results must also return to the project. Copilot's documentation can stay in the Library; sessions and PRs are discoverable from Overview. Cursor can update the shared task, writing result links back to Context. Raw test results remain in CI, accessible via links.
"Tested" should be followed by "which version, what was tested." When related code changes later, there's a basis to decide if old results still apply.
Session Ends, Project Continues
Days later, an agent responsible for cleaning up the old field arrives. The previous two sessions have ended; backend and client PRs are merged. Yet it cannot simply delete nickname.
One thing remains: has the legacy app met its exit criteria? Until confirmed, the old field must stay. Migration progress is judged by the overall convention, not by counting merged PRs.
Architecturally, the key is:
This information must outlive a single Session.
A Session has its own context for completing the immediate work. Project preserves the migration goal, current convention, task status, and result entry points. A new agent enters, queries what its step needs; after finishing, writes new progress and results back.
Thus the backend session can end, the client can switch agents, and old-field cleanup can happen days later. Multiple execution rounds revolve around the same migration goal; confirmed and pending items have a place to continue tracking.
We already rely on design docs, task systems, and handoff records for this. When docs miss details or progress isn't updated, we call the original colleague to fill gaps. Project attempts to embed these actions into the agent's workflow: check current records before starting, update progress after finishing, ask when information is missing. Mastering these steps gives humans a chance to reduce background preparation.
However, recorded information can be lost to later updates. In the September early beta, developer Lutz Leonhardt reported that a decision he had confirmed disappeared after the project notes were rewritten twice; the next day the agent asked again. This was his personal experience with that beta, not a conclusion about the current version.
Therefore, managing how records are updated remains critical. Finalized conventions must not vanish silently during note reorganization; when approaches change, later people must know which one is obsolete. Otherwise the explanation burden returns to humans.
In our earlier breakdown of DeepSeek Super-agent (https://mp.weixin.qq.com/s?__biz=MzAwNjQwNzU2NQ==∣=2650410862&idx=1&sn=0c38f8c34cd8194d84bf2be3f039e15a&scene=21#wechat_redirect), we discussed how the Router dispatches work and Workers bring back PRs. This article continues from the PR return: where the remaining work lives and how the next agent picks it up.
Starting with One Handoff
To apply this thinking, try a single handoff. Use the same field migration: take an existing Issue as entry point, document where the convention lives, who has done what, and where to find results.
For example, after the backend submits a PR, leave this in the Issue:
Current convention at docs/profile-api.md in the repo. Dual-field coexistence; the original requirement's "direct replacement" was corrected by this review. Backend PR #84 awaiting review, tracked by backend colleague. Commit a1b2c3d CI #315 verified dual-field return with identical values. Client not started, owned by client colleague, no execution session assigned yet. Old-field cleanup still waiting. Legacy app exit criteria to be confirmed by client lead; result to be backfilled here.
The interface contract stays in the design doc; test details stay in CI. The Issue simply threads the entry points together. When the approach changes, add a note in the task about what changed and why; later people and agents can trace it.
When the client colleague prepares to launch an agent, they first confirm ownership on this Issue, then have the agent read the contract, backend PR, and tests. Once started, link the execution session back to the task for discoverability. Task instructions can be more specific:
In unit tests, make the two fields take different values to confirm the client reads display_name . After completion, backfill the client PR, corresponding commit, and test results in this Issue, preserving the old-field cleanup waiting state.
If another colleague is already working on it, clarify who continues to avoid duplicate work. If two documents conflict, ask which is authoritative. Record the owner or decision back to the relevant record so the next person asks one less time.
Then start a fresh session, give it only this Issue, and observe how it handles the handoff.
Can it find the reason for keeping the old field, recognize the colleague's in-progress task, and distinguish what backend vs. client tested? If it still needs a full walkthrough, add records where it got stuck. This quickly reveals what the handoff lacks.
Back to the start: your agent first discovers a colleague is already on it, locates their PR and tests, knows which step to take next — saving one full restart and one manual relay.
Sessions can end; unfinished work still has a place to continue. This is the most valuable takeaway from the shift from Session to Project.
References
GitHub Docs, Working with projects in the GitHub Copilot app (https://docs.github.com/en/copilot/how-tos/github-copilot-app/working-with-projects)
GitHub Docs, Working with agent sessions in the GitHub Copilot app (https://docs.github.com/en/copilot/how-tos/github-copilot-app/agent-sessions)
Cursor Docs, Projects (https://cursor.com/docs/agent/projects)
Cursor Docs, Release notes, 3.27 Projects (https://prod.cursor.com/docs/release-notes)
Cursor, Multiplayer Projects announcement (https://x.com/cursor_ai/status/2120295553309565139)
Elliot Hesp, Multiplayer Cursor Projects (https://forum.cursor.com/t/multiplayer-cursor-projects/175478)
Lutz Leonhardt, I tested the Projects beta for three days (https://forum.cursor.com/t/i-tested-the-projects-beta-for-three-days-what-worked-and-where-decisions-got-lost/172974)
架构师, Architecture breakdown: DeepSeek's newly released Super-agent (https://mp.weixin.qq.com/s?__biz=MzAwNjQwNzU2NQ==∣=2650410862&idx=1&sn=0c38f8c34cd8194d84bf2be3f039e15a&chksm=83037b8cb474f29a3d719a40fa0bd8bd6bf8a3089b4529017916d959450ed7afb8996ad9c9b8#rd)
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
