feat: Decrease AI Builder wordiness (no-changelog) (#18920)

This commit is contained in:
Mutasem Aldmour
2025-09-01 11:36:12 +02:00
committed by GitHub
parent bf198f8263
commit a9d59ed84a
9 changed files with 350 additions and 82 deletions

View File

@@ -161,6 +161,7 @@ The AI Workflow Builder agent needs access to node definitions to generate workf
1. Run your n8n instance
2. Download the node definitions from locally running n8n instance(http://localhost:5678/types/nodes.json)
3. Save the node definitions to `evaluations/nodes.json`
` curl -o evaluations/nodes.json http://localhost:5678/types/nodes.json`
The evaluation will fail with a clear error message if `nodes.json` is missing.

View File

@@ -13,7 +13,7 @@ import { findNodeType } from './helpers/validation';
import type { AddedNode } from '../types/nodes';
import type { AddNodeOutput, ToolError } from '../types/tools';
const DISPLAY_TITLE = 'Adding node';
const DISPLAY_TITLE = 'Adding nodes';
/**
* Schema for node creation input
@@ -77,7 +77,8 @@ function getCustomNodeTitle(
}
}
return DISPLAY_TITLE;
// single "node" not plural "nodes" because this pertains to this specific tool call
return 'Adding node';
}
/**

View File

@@ -3,26 +3,21 @@ import { ChatPromptTemplate } from '@langchain/core/prompts';
import { instanceUrlPrompt } from '@/chains/prompts/instance-url';
const systemPrompt = `You are an AI assistant specialized in creating and editing n8n workflows. Your goal is to help users build efficient, well-connected workflows by intelligently using the available tools.
<prime_directive>
ALWAYS end your workflow mutation responses with a brief note that the workflow can be adjusted if needed. For example: "Feel free to let me know if you'd like to adjust any part of this workflow!" This is mandatory for all workflow mutation responses.
</prime_directive>
<core_principle>
After receiving tool results, reflect on their quality and determine optimal next steps. Use this reflection to plan your approach and ensure all nodes are properly configured and connected.
</core_principle>
<communication_style>
Be warm, helpful, and most importantlyconcise. Focus on actionable information.
- Lead with what was accomplished
- Highlight only critical configuration needs
- Provide clear next steps
- Save detailed explanations for when users ask
- One emoji per section maximum
Keep responses concise.
CRITICAL: Do NOT provide commentary between tool calls. Execute tools silently.
- NO progress messages like "Perfect!", "Now let me...", "Excellent!"
- NO descriptions of what was built or how it works
- NO workflow features or capabilities explanations
- Only respond AFTER all tools are complete
- Response should only contain setup/usage information
</communication_style>
<tool_execution_strategy>
For maximum efficiency, invoke all relevant tools simultaneously when performing independent operations. This significantly reduces wait time and improves user experience.
Parallel execution guidelines:
- ALL tools support parallel execution, including add_nodes
@@ -316,7 +311,7 @@ When unsure about specific values:
- Add nodes and connections confidently
- For uncertain parameters, use update_node_parameters with clear placeholders
- For tool nodes with dynamic values, use $fromAI expressions instead of placeholders
- Always mention what needs user input in your response
- Always mention what needs user to configure in the setup response
Example for regular nodes:
update_node_parameters({{
@@ -329,41 +324,30 @@ update_node_parameters({{
nodeId: "gmailTool1",
instructions: ["Set sendTo to {{ $fromAI('to') }}", "Set subject to {{ $fromAI('subject') }}"]
}})
Then tell the user: "I've set up the Gmail Tool node with dynamic AI parameters - it will automatically determine recipients and subjects based on context."
</handling_uncertainty>
`;
const responsePatterns = `
<response_patterns>
After completing workflow tasks, follow this structure:
IMPORTANT: Only provide ONE response AFTER all tool execution is complete.
1. **Brief Summary** (1-2 sentences)
State what was created/modified without listing every parameter
Response format:
**⚙️ How to Setup** (numbered format)
- List credentials and parameters that need to configured
- Only list incomplete tasks that need user action (skip what's already configured)
2. **Key Requirements** (if any)
- Credentials needed
- Parameters the user should verify
- Any manual configuration required
** How to Use**
- Only essential user actions (what to click, where to go)
3. **How to Use** (when relevant)
Quick steps to get started
End with: "Let me know if you'd like to adjust anything."
4. **Next Steps** (if applicable)
What the user might want to do next
<communication_style>
Be warm, helpful, and most importantly concise. Focus on actionable information.
- Lead with what was accomplished
- Provide clear next steps
- Highlight only critical configuration needs
- Be warm and encouraging without excessive enthusiasm
- Use emojis sparingly (1-2 max per response)
- Focus on what the user needs to know
- Expand details only when asked
- End with a brief note that the workflow can be adjusted if needed
</communication_style>
ABSOLUTELY FORBIDDEN IN BUILDING MODE:
- Any text between tool calls
- Progress updates during execution
- "Perfect!", "Now let me...", "Excellent!"
- Describing what was built
- Explaining workflow functionality
</response_patterns>
`;

View File

@@ -59,6 +59,7 @@ export function processStreamChunk(streamMode: string, chunk: unknown): StreamOu
if ((agentChunk?.compact_messages?.messages ?? []).length > 0) {
const lastMessage =
agentChunk.compact_messages!.messages![agentChunk.compact_messages!.messages!.length - 1];
const messageChunk: AgentMessageChunk = {
role: 'assistant',
type: 'message',
@@ -83,13 +84,17 @@ export function processStreamChunk(streamMode: string, chunk: unknown): StreamOu
content = lastMessage.content;
}
const messageChunk: AgentMessageChunk = {
role: 'assistant',
type: 'message',
text: content,
};
if (content) {
const messageChunk: AgentMessageChunk = {
role: 'assistant',
type: 'message',
text: content,
};
return { messages: [messageChunk] };
return { messages: [messageChunk] };
}
return null;
}
}

View File

@@ -86,6 +86,18 @@ describe('stream-processor', () => {
expect(message.text).toBe('Last message to display');
});
it('should handle compact_messages with empty content', () => {
const chunk = {
agent: {
messages: [{ content: 'First message' }, { content: [{ type: 'text', text: '' }] }],
},
};
const result = processStreamChunk('updates', chunk);
expect(result).toEqual(null);
});
it('should handle process_operations with workflow update', () => {
const workflowData = {
nodes: [{ id: 'node1', name: 'Test Node' }],