feat(conversation): add aioncore conversation create for agent-driven conversation creation - #977
Merged
Merged
Conversation
added 6 commits
September 8, 2026 15:53
…ranch and provider repo hook
…provider matching
…ind runtime-token auth
…driven conversation creation
piorpua
pushed a commit
that referenced
this pull request
Sep 9, 2026
🤖 I have created a release *beep* *boop* --- ## [0.2.2](v0.2.1...v0.2.2) (2026-09-09) ### Features * **conversation:** add aioncore conversation create for agent-driven conversation creation ([#977](#977)) ([23daff5](23daff5)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Lets an agent create a new conversation for the same user from inside its own conversation, so "open a fresh conversation for this task and hand it over" no longer needs the user to create and name an empty conversation by hand first.
aioncore conversation capabilities | create, payload over stdin ({ name, workspace?, assistant_id? }), wired to one runtime route that authenticates with the existing per-conversation helper token (no new scope, no change to token issuance).model). Both can be overridden: an explicitworkspacemust be an absolute path to an existing directory; an explicitassistant_idmust name an existing, enabled assistant.assistant_model_unresolved; the caller's model is never used as a silent fallback.success: trueenvelope means the row, its assistant snapshot, and the ACP session row are persisted andconversation.listChanged(created)has been broadcast, so the id can be used immediately (for example as asession send-messagetarget). The runtime starts lazily on the first message, exactly like a manually created empty conversation.conversation-create). Neither skill references the other; combining "create, then deliver" is left to the agent.conversation.listChanged.Design decisions worth a reviewer's attention
POST /api/conversations. Inheriting from the caller requires knowing who the caller is; the route takes it from the token-boundx-aionui-conversation-idheader, so the body cannot name a different caller and the agent never has to assemble a fullCreateConversationRequest(the aionrsmodelshape in particular).ConversationService::createis called, in a fixed order (caller row → team → name → workspace → assistant), so a rejection never leaves a half-built conversation behind and a request matching several rejections always returns the same code.createfor everything after resolution — assistant snapshot, skills, MCP, rules, workspace existence check — rather than re-implementing any of it.custom_workspace: trueis passed only becausecreatestrips it; the non-emptyextra.workspaceis what suppresses temp-dir provisioning.type+extra.{backend, agent_id, agent_source}triple when the caller has no snapshot or its assistant definition has since been deleted, so the new conversation still mirrors the caller instead of failing with an error the agent cannot act on.cmd_session.rs's envelope/stdin plumbing instead of abstracting it: the two families have different envelope and error-code types, and a generic layer is not worth it until a third family appears.conversation created by agentline per success withfrom_conversation_id / conversation_id / inheritance / workspace_inherited / model_resolution / backend, and oneagent conversation create refusedwarn per rejection withfrom_conversation_id / error_code / outcome. Conversation names, workspace paths, model ids, and header values are never logged.aionui-config/cron: untickingconversation-createremoves the agent's guidance, not the server's willingness to answer a valid runtime token. The command family also appears in the top-levelaioncore capabilitiesindex, so an agent can still discover it there.Migration
None.
Verified in a development environment
Beyond unit, integration, and binary end-to-end tests, the feature was exercised in a dev build against real agent CLIs (direct-CLI and ACP backends), with each observation cross-checked against backend logs and the persisted rows:
namefrom a claude-backed conversation: workspace and assistant snapshot inherited,source=aionui,name_sourceunset, onelistChanged(created)broadcast; the agent then delivered a task to the new conversation viasession send-messageand received the reply, with the new conversation's runtime starting lazily on that first message.namefrom an aionrs conversation: the storedmodel(provider + model) inherited verbatim.workspacepersisted as given, with no temp workspace provisioned.assistant_idfor an ACP assistant: backend and agent taken from that assistant, no top-level model.assistant_idfor an aionrs assistant:model.provider_idresolved to the single enabled provider offering its default model.caller_is_team), unknown assistant (assistant_not_found), non-existent absolute workspace (workspace_unavailable, directory not created), relative workspace (workspace_not_absolute). The last two required invoking the CLI directly, because the skill rules made the agent pre-check them itself.aioncore capabilities, consistent with the other built-in CLI families.Not exercised in the dev build (covered by service-level integration tests):
assistant_disabled,assistant_model_unresolved, and the legacy-triple fallback, each of which needs a specially constructed configuration.Screenshots are omitted: the observable behavior is a new sidebar entry plus log and database state, all of which is captured by the automated tests and the log/DB checks above.
Test plan
cargo fmt --all -- --checkcargo clippy --all-targets -- -D warningsonaionui-api-types,aionui-conversation,aionui-appcargo teston the three affected crates (new: registry/error-code unit tests; service-level inherit/override/bad-path tests; route-level auth/status/code tests; real-router e2e; real-binary CLI e2e; skill content guards)just push