Skip to content

[Feat] AI-guided agent creation dialog#261

Merged
samzong merged 2 commits intomainfrom
feat/agent-builder-dialog
Apr 2, 2026
Merged

[Feat] AI-guided agent creation dialog#261
samzong merged 2 commits intomainfrom
feat/agent-builder-dialog

Conversation

@samzong
Copy link
Copy Markdown
Collaborator

@samzong samzong commented Apr 2, 2026

Summary

Add an AI Builder dialog that guides users through creating a new Agent via conversational AI. The dialog uses the existing system session service to power a chat interface, with a live preview panel showing the agent configuration as it evolves.

Type of change

  • [Feat] new feature
  • [Fix] bug fix

Why is this needed?

Creating an Agent currently requires filling out a form manually. The AI Builder provides a guided, conversational experience that helps users define an agent's name, model, and identity through natural language — lowering the barrier for non-technical users.

Along the way, two pre-existing bugs in the system session service were discovered and fixed:

  1. Session key prefix mismatch: buildSystemSessionKey omitted the agent:{agentId}: prefix, causing event handler to drop all system session events
  2. Text extraction: system session used payload.text directly instead of extractText(), missing structured content blocks from the Gateway

What changed?

  • New AgentBuilderDialog component with left chat panel + right preview card
  • New useSystemSession hook bridging core store/service to React
  • system-session-service: use extractText() from protocol layer, import canonical ChatEventPayload type
  • buildSystemSessionKey in shared: include agent:{agentId}: prefix to match Gateway event routing
  • isSystemSession regex updated to match new prefixed format
  • Platform index: wire system session store + service with lazy proxy pattern
  • AgentsSection: add AI Builder button next to manual "Add Agent"
  • Dialog UX: prevents outside-click close, X button requires confirmation, try/catch/finally for create flow
  • Workspace path built from getWorkspacePath() + slug (not bare slug)
  • Identity written to IDENTITY.md (Gateway-allowed file name)
  • System prompt enforces English ASCII agent names, responds in user locale
  • i18n: 9 new keys across 8 locales

Architecture impact

  • Owning layer: shared / core / renderer
  • Cross-layer impact: yes — shared buildSystemSessionKey signature changed (new optional agentId param, backward compatible), core service imports extractText from protocol layer
  • Invariants touched from docs/architecture-invariants.md: session key format
  • Why those invariants remain protected: system session keys now follow the same agent:{agentId}: prefix convention as task session keys, ensuring Gateway event routing works correctly

Linked issues

Closes #260

Validation

  • pnpm lint
  • pnpm test
  • pnpm check:ui-contract
  • pnpm check (full gate: lint + architecture + ui-contract + renderer-copy + i18n + dead-code + format + typecheck + test)
  • Manual smoke test

Commands, screenshots, or notes:

pnpm check — all 273 tests pass, all checks green

Screenshots or recordings

Dialog layout: left chat panel with AI conversation, right panel with live agent config preview (name, model, identity). CSS variables used for all colors, design tokens for spacing. max-w-5xl and h-144 for dialog dimensions. Close button uses confirmation prompt via window.confirm().

Release note

  • User-facing change. Release note is included below.
Added AI Builder dialog for creating Agents through guided conversation. Access it from the Agents settings section.

Checklist

  • The PR title uses at least one approved prefix: [Feat], [Fix], [UI], [Docs], [Refactor], [Build], or [Chore]
  • The summary explains both what changed and why
  • Validation reflects the commands actually run for this PR
  • Architecture impact is described and references any touched invariants
  • Cross-layer changes are explicitly justified
  • The release note block is accurate

- New AgentBuilderDialog component with chat + live preview panel
- System session service: fix session key prefix and text extraction
- Three-step serial create flow (createAgent → updateAgent → setAgentFile)
- Dialog prevents accidental close with confirmation prompt
- Workspace path derived from app config, not bare slug
- AI responds in user locale, agent name enforced as ASCII
- i18n: 8 new keys across 8 locales

Signed-off-by: samzong <samzong.lu@gmail.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 2, 2026

Hi @samzong,
Thanks for your pull request!
If the PR is ready, use the /auto-cc command to assign Reviewer to Review.
We will review it shortly.

Details

Instructions for interacting with me using comments are available here.
If you have questions or suggestions related to my behavior, please file an issue against the gh-ci-bot repository.

@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages bot commented Apr 2, 2026

Deploying cpwa with  Cloudflare Pages  Cloudflare Pages

Latest commit: 40c9472
Status: ✅  Deploy successful!
Preview URL: https://12fd2598.cpwa.pages.dev
Branch Preview URL: https://feat-agent-builder-dialog.cpwa.pages.dev

View logs

@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a significant new feature: an AI Builder dialog designed to simplify the creation of new AI Agents. Instead of manually filling out forms, users can now interact with a conversational AI to define an agent's name, model, and identity, making the process more intuitive, especially for non-technical users. The dialog also provides a live preview of the agent's configuration as it's being built. Additionally, the PR includes crucial bug fixes to the underlying system session service, ensuring robust and correct handling of AI-related events.

Highlights

  • AI-Guided Agent Creation Dialog: Introduced a new AgentBuilderDialog component that provides a conversational AI interface for creating new agents, complete with a live preview of the agent's configuration.
  • System Session Service Enhancements: Implemented a new useSystemSession React hook and updated the core system-session-service to correctly extract text from structured content blocks and handle session events more robustly.
  • Session Key Format Correction: Fixed a critical bug by updating the buildSystemSessionKey function and isSystemSession regex to include an agent:{agentId}: prefix, ensuring proper routing of system session events in the Gateway.
  • Improved User Experience: Enhanced the agent creation flow by offering an intuitive, conversational alternative to manual form filling, lowering the barrier for non-technical users.
  • Internationalization Support: Added new translation keys across 8 locales to support the new AI Builder dialog, ensuring a localized experience for users.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces an AI-driven Agent Builder, allowing users to configure new agents through a guided chat interface. Key changes include the implementation of the AgentBuilderDialog component, a useSystemSession hook, and updates to the system-session-service to support agent-specific session keys. Review feedback highlights several discrepancies between the implementation and the intended design specifications, specifically regarding instruction file naming, dialog dimensions, and a missing exit confirmation prompt. Additionally, improvements were suggested for real-time configuration parsing during streaming and more robust sanitization of workspace slugs.

}

if (config.identity.trim() && agentId) {
const fileRes = await window.clawwork.setAgentFile(gatewayId, agentId, 'instructions.md', config.identity.trim());
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

There is a discrepancy between the code and the PR description. The description states the identity is written to IDENTITY.md (noting it as a Gateway-allowed filename), but the code uses instructions.md. Please verify the correct filename requirement for the Gateway to ensure the identity is correctly persisted and recognized.

Suggested change
const fileRes = await window.clawwork.setAgentFile(gatewayId, agentId, 'instructions.md', config.identity.trim());
const fileRes = await window.clawwork.setAgentFile(gatewayId, agentId, 'IDENTITY.md', config.identity.trim());

}, [open, gatewayId, defaultAgentId, models, start, i18n.language]);

useEffect(() => {
if (prevStatusRef.current === 'streaming' && status === 'active') {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The current implementation only updates the configuration preview when the session transitions from streaming to active (at the end of a message). To provide the "live preview" mentioned in the PR description, the configuration should also be parsed while the status is streaming so the preview updates as the AI generates the JSON block.

Suggested change
if (prevStatusRef.current === 'streaming' && status === 'active') {
if (status === 'streaming' || (prevStatusRef.current === 'streaming' && status === 'active')) {

if (!config.name.trim()) return;
setCreating(true);

const slug = deriveWorkspace(config.name) || config.name.trim().toLowerCase();
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The fallback for slug uses the raw trimmed name, which may contain characters invalid for file system paths (e.g., /, \). Since deriveWorkspace is intended to sanitize the name into a safe slug, it should be used exclusively or the fallback should be properly sanitized to ensure a valid workspace path is created.

Suggested change
const slug = deriveWorkspace(config.name) || config.name.trim().toLowerCase();
const slug = deriveWorkspace(config.name) || 'new-agent';

Comment on lines +243 to +251
const handleClose = useCallback(
(nextOpen: boolean) => {
if (!nextOpen && !creating) {
end();
onOpenChange(false);
}
},
[creating, end, onOpenChange],
);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The handleClose function is missing the confirmation prompt (window.confirm()) mentioned in the PR description. This is important to prevent users from accidentally losing their conversation progress. Note that the corresponding i18n key for the confirmation message also appears to be missing from the locale files.

  const handleClose = useCallback(
    (nextOpen: boolean) => {
      if (!nextOpen && !creating) {
        if (messages.length > 1 && !window.confirm(t('settings.agentBuilderConfirmClose'))) {
          return;
        }
        end();
        onOpenChange(false);
      }
    },
    [creating, end, messages.length, onOpenChange, t],
  );


return (
<Dialog open={open} onOpenChange={handleClose}>
<DialogContent className="max-w-4xl p-0 overflow-hidden">
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The dialog width max-w-4xl does not match the max-w-5xl specification mentioned in the PR description.

Suggested change
<DialogContent className="max-w-4xl p-0 overflow-hidden">
<DialogContent className="max-w-5xl p-0 overflow-hidden">

<DialogDescription>{t('settings.agentBuilderDesc')}</DialogDescription>
</DialogHeader>

<div className="flex h-128 border-t border-[var(--border-subtle)]">
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The dialog height h-128 does not match the h-144 specification mentioned in the PR description.

Suggested change
<div className="flex h-128 border-t border-[var(--border-subtle)]">
<div className="flex h-144 border-t border-[var(--border-subtle)]">

- Use IDENTITY.md instead of instructions.md (Gateway whitelist)
- Dialog: max-w-5xl, h-144, block outside-click, X requires confirm
- try/catch/finally for create flow to prevent dialog vanishing on error
- Parse agent-config during streaming for real-time preview
- Workspace slug fallback: safe "new-agent" instead of raw name
- System prompt: respond in user locale, enforce ASCII agent names
- i18n: add agentBuilderCloseConfirm key across 8 locales

Signed-off-by: samzong <samzong.lu@gmail.com>
@samzong
Copy link
Copy Markdown
Collaborator Author

samzong commented Apr 2, 2026

/gemini review

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 2, 2026

@samzong

I encountered an error while processing your command:

❌ Unknown command /gemini. Please check the available commands and try again.

Details

Instructions for interacting with me using comments are available here.
If you have questions or suggestions related to my behavior, please file an issue against the gh-ci-bot repository.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces an AI-driven Agent Builder feature, enabling users to create and configure agents through a guided conversation. Key additions include the AgentBuilderDialog component, a useSystemSession hook, and updates to the system session service and session key format to support agent-specific identifiers. The review feedback identifies several critical improvements: ensuring the agent creation process is atomic to avoid partial failures, normalizing file paths for Windows compatibility, replacing native browser dialogs with themed components to follow the style guide, and enforcing ASCII validation for agent names in the UI.

Comment on lines +204 to +233
const createRes = await window.clawwork.createAgent(gatewayId, {
name: config.name.trim(),
workspace,
});
if (!createRes.ok) {
toast.error(createRes.error ?? t('errors.failed'));
return;
}

const created = createRes.result as Record<string, unknown> | undefined;
const agentId = (created?.agentId as string) ?? '';

if (config.model.trim() && agentId) {
const updateRes = await window.clawwork.updateAgent(gatewayId, {
agentId,
model: config.model.trim(),
});
if (!updateRes.ok) {
toast.error(updateRes.error ?? t('errors.failed'));
return;
}
}

if (config.identity.trim() && agentId) {
const fileRes = await window.clawwork.setAgentFile(gatewayId, agentId, 'IDENTITY.md', config.identity.trim());
if (!fileRes.ok) {
toast.error(fileRes.error ?? t('errors.failed'));
return;
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

The agent creation process is not atomic, as it relies on three separate IPC calls (createAgent, updateAgent, setAgentFile). If the first call succeeds but subsequent ones fail, an incomplete agent is left behind. This can cause issues when the user tries to recreate the agent with the same name/workspace. Consider implementing a rollback mechanism that deletes the agent if configuration fails.

try {
const slug = deriveWorkspace(config.name) || 'new-agent';
const wsBase = await window.clawwork.getWorkspacePath();
const workspace = wsBase ? `${wsBase}/${slug}` : slug;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Manual path construction using a hardcoded forward slash can lead to incorrect paths on Windows or double separators if wsBase already ends with one. Since the renderer lacks access to the path module, consider normalizing the base path before joining.

Suggested change
const workspace = wsBase ? `${wsBase}/${slug}` : slug;
const workspace = wsBase ? `${wsBase.replace(/[\\/]$/, "")}/${slug}` : slug;

const requestClose = useCallback(() => {
if (creating) return;
const hasConversation = messages.length > 1;
if (hasConversation && !window.confirm(t('settings.agentBuilderCloseConfirm'))) return;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Using window.confirm is discouraged as it blocks the renderer thread and doesn't adhere to the application's styling and design tokens. It's better to use a custom React-based modal or an IPC call to the main process's native dialog API for a more consistent user experience.

References
  1. Renderer / UI changes should use themed components and design tokens rather than browser natives. (link)

<input
type="text"
value={config.name}
onChange={(e) => updateConfigField('name', e.target.value)}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The system prompt requires the agent name to be ASCII-only for use as a system identifier. While the AI is instructed to follow this, the UI allows the user to manually enter non-ASCII characters in the preview panel. Validation should be added to ensure the name remains compatible with system requirements.

Suggested change
onChange={(e) => updateConfigField('name', e.target.value)}
onChange={(e) => { const val = e.target.value; if (/^[ -~]*$/.test(val)) updateConfigField("name", val); }}

@samzong samzong merged commit 51e483a into main Apr 2, 2026
16 of 17 checks passed
@samzong samzong deleted the feat/agent-builder-dialog branch April 2, 2026 17:12
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.

1 participant