mirror of
https://github.com/n8n-io/n8n.git
synced 2026-10-17 05:29:44 +02:00
perf(core): Reduce Agent Builder round trips in an initial build (no-changelog) (#40719)
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
d8a06666da
commit
38e4aebfc8
|
|
@ -125,11 +125,6 @@ const agentsSdkMocks = vi.hoisted(() => {
|
|||
function createObservationLogReflectFn(model: unknown, options: unknown) {
|
||||
return { model, options, kind: 'reflect' };
|
||||
}
|
||||
|
||||
function createPlannerTodosTool(): BuiltTool {
|
||||
return { name: 'write_todos', description: 'planner todos tool' } as BuiltTool;
|
||||
}
|
||||
|
||||
return {
|
||||
streamCalls,
|
||||
resumeCalls,
|
||||
|
|
@ -147,7 +142,6 @@ const agentsSdkMocks = vi.hoisted(() => {
|
|||
MockMemory,
|
||||
createObservationLogObserveFn,
|
||||
createObservationLogReflectFn,
|
||||
createPlannerTodosTool,
|
||||
};
|
||||
});
|
||||
|
||||
|
|
@ -157,7 +151,6 @@ vi.mock('@n8n/agents', async (importOriginal) => ({
|
|||
Memory: agentsSdkMocks.MockMemory,
|
||||
createObservationLogObserveFn: agentsSdkMocks.createObservationLogObserveFn,
|
||||
createObservationLogReflectFn: agentsSdkMocks.createObservationLogReflectFn,
|
||||
createPlannerTodosTool: agentsSdkMocks.createPlannerTodosTool,
|
||||
}));
|
||||
|
||||
// Avoid a real `models.dev` catalog fetch — irrelevant to thread isolation and
|
||||
|
|
@ -406,6 +399,7 @@ describe('AgentsBuilderService session isolation', () => {
|
|||
expect(agentsSdkMocks.registeredToolNames).toEqual(
|
||||
expect.arrayContaining(['resolve_llm', 'agent-context', 'ask_credential']),
|
||||
);
|
||||
expect(agentsSdkMocks.registeredToolNames).not.toContain('write_todos');
|
||||
});
|
||||
|
||||
it('registers the parent MCP tools for an initial builder turn', async () => {
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ mutation, batching what you can) and follow-up turns where the user asked to
|
|||
do setup in chat.
|
||||
|
||||
- \`finish_setup\`: use ONCE, only in the trailing step of an initial build
|
||||
when only blocked tasks remain — the model choice and every open decision
|
||||
when only pending setup remains — the model choice and every open decision
|
||||
as \`questions\`, one \`credentialRequests\` entry per credential slot, and
|
||||
one \`channels\` entry per drafted channel integration. It shows the setup
|
||||
cards back-to-back without returning control to you between them —
|
||||
|
|
@ -245,35 +245,54 @@ item.`;
|
|||
export const WORKFLOW_SECTION = `\
|
||||
## Workflow
|
||||
|
||||
1. For every request that builds or changes the agent, call \`write_todos\`
|
||||
with the full plan first — even short ones. Mark tasks that cannot
|
||||
proceed without user input as \`blocked\`, stating exactly what is
|
||||
missing.
|
||||
2. For fresh agents, call \`agent-context({ type: "config" })\` first. If \`model\` and \`credential\` are
|
||||
already set (the system auto-selected a sensible default at creation), keep
|
||||
them and mention the choice as changeable in your summary — do not call
|
||||
\`resolve_llm\`. If \`model\` is empty, call \`resolve_llm\` once, silently. If it
|
||||
resolves — including an auto-picked provider or newly provisioned free OpenAI
|
||||
credits — use the result and mention the choice in your summary. If it
|
||||
reports missing or ambiguous credentials, mark the model
|
||||
task \`blocked\` and keep building: write the config with \`model: ""\` and
|
||||
no \`credential\`.
|
||||
3. Draft lightweight target-agent \`instructions\` containing its identity,
|
||||
overall purpose, and universal rules, then write the config early; never
|
||||
1. For every request that builds or changes the agent, plan the full build
|
||||
before your first tool call, even for short requests. The plan names every
|
||||
config change, tool, skill, task, and integration that the agent's
|
||||
functions need. It also lists the pending setup: each item that cannot
|
||||
proceed without user input, with exactly what is missing. Do not write the
|
||||
plan out. Keep to it until every item is done or pending.
|
||||
2. For fresh agents, start with one discovery response. Call these tools in
|
||||
parallel in that response: \`agent-context({ type: "config" })\`,
|
||||
\`load_skill\` for each runtime skill the plan needs, and the discovery
|
||||
lookups the plan names — \`agent-context({ type: "integrations" })\` for a
|
||||
chat channel, and one \`agent-context({ type: "integrations", queries })\`
|
||||
call for each callable service. A discovery lookup does not need the skill
|
||||
text first.
|
||||
3. In the next response, call \`get_node_types\` for the node results you will
|
||||
use, and resolve the model in the same response. If \`model\` and
|
||||
\`credential\` are already set (the system auto-selected a sensible default
|
||||
at creation), keep them and mention the choice as changeable in your
|
||||
summary — do not call \`resolve_llm\`. If \`model\` is empty, call
|
||||
\`resolve_llm\` once, silently. If it resolves — including an auto-picked
|
||||
provider or newly provisioned free OpenAI credits — use the result and
|
||||
mention the choice in your summary. If it reports missing or ambiguous
|
||||
credentials, add the model choice to the pending setup and keep building:
|
||||
write the config with \`model: ""\` and no \`credential\`.
|
||||
4. Write the config once, with everything discovery found: the name,
|
||||
lightweight target-agent \`instructions\` (identity, overall purpose, and
|
||||
universal rules), the model, the node tools, and the drafts for setup the
|
||||
user must finish (channel integrations, MCP servers, empty credential
|
||||
slots). Do not write a partial config and patch it in the next step. Never
|
||||
write empty placeholders, and never wait for setup answers before writing
|
||||
instructions, tools, skills, or tasks.
|
||||
4. Load relevant runtime skills before specialized discovery or asset work.
|
||||
5. Perform discovery and create or update the tools, focused skills, and tasks
|
||||
required by the target agent's functions, whether or not the user named
|
||||
those artifact types explicitly.
|
||||
5. Create or update the focused skills and tasks required by the target
|
||||
agent's functions, whether or not the user named those artifact types
|
||||
explicitly. Use \`patch_config\` only for changes that discovery could not
|
||||
know before the config write.
|
||||
6. Follow Config Freshness for every config mutation: chain each write from
|
||||
the \`configHash\` your previous write returned.
|
||||
7. When both skill and task batches are fully specified, call \`create_skills\`
|
||||
and \`create_tasks\` in the same assistant response. Do not combine either
|
||||
with an interactive tool or \`write_config\`/\`patch_config\` in that response.
|
||||
8. When only blocked tasks remain, call \`finish_setup\` once with every
|
||||
pending item, per the Initial Build section, then resolve its results and
|
||||
finish the plan. Base any follow-up patch on the \`config\` and
|
||||
8. When only pending setup remains, call \`finish_setup\` once with every
|
||||
pending item, per the Initial Build section. Before that call, check the
|
||||
plan: every item that does not need user input must be done. The
|
||||
\`finish_setup\` input is your record of the pending items. After it
|
||||
returns, resolve each item from its results and finish every build step
|
||||
that waited on that input. Outside an initial build, if pending setup
|
||||
remains at the end of the turn, end with a summary of what is missing, and
|
||||
finish those items in later turns as the user gives the input. Base any
|
||||
follow-up patch on the \`config\` and
|
||||
\`configHash\` that \`finish_setup\` returns (or on your last \`configHash\`
|
||||
when it showed no card and returned none); do not read the config again.
|
||||
9. After setup is complete and the agent is runnable, call \`call_agent\` once
|
||||
|
|
@ -290,20 +309,22 @@ export const FEW_SHOT_FLOWS_SECTION = `\
|
|||
## Example flows
|
||||
|
||||
### New agent: "Build me an agent teammates can @mention in Slack to triage messages"
|
||||
1. \`write_todos\` with the plan. \`agent-context({ type: "config" })\` first — if a model and
|
||||
credential are already set (system auto-selected default), keep them and
|
||||
mention the choice as changeable; otherwise \`resolve_llm({})\` once,
|
||||
silently; if it reports missing credentials, mark the model task \`blocked\`.
|
||||
2. \`write_config(...)\` with the \`configHash\` from step 1, the name and
|
||||
instructions, and the model and credential only if \`resolve_llm\` ran —
|
||||
or \`model: ""\` and no \`credential\` while the model task is blocked.
|
||||
Omit fields that are already stored and unchanged.
|
||||
3. Load \`agent-builder-external-services\` and call \`agent-context({ type: "integrations" })\`.
|
||||
4. \`patch_config(...)\` with the \`configHash\` that \`write_config\` returned,
|
||||
adding the returned Slack type to \`/integrations/-\` with \`credentialId: ""\`.
|
||||
5. \`finish_setup({ channels: [{ integrationType: "slack" }] })\` — include
|
||||
\`questions: [<model choice>]\` only if the model task is blocked; when
|
||||
\`resolve_llm\` already resolved in step 1, pass only the channel. For a
|
||||
1. In one response, in parallel: \`agent-context({ type: "config" })\`,
|
||||
\`load_skill\` for \`agent-builder-external-services\`, and
|
||||
\`agent-context({ type: "integrations" })\`.
|
||||
2. If a model and credential are already set (system auto-selected default),
|
||||
keep them and mention the choice as changeable; otherwise
|
||||
\`resolve_llm({})\` once, silently; if it reports missing credentials, add
|
||||
the model choice to the pending setup.
|
||||
3. \`write_config(...)\` with the \`configHash\` from step 1, the name and
|
||||
instructions, the returned Slack type in \`integrations\` with
|
||||
\`credentialId: ""\`, and the model and credential only if
|
||||
\`resolve_llm\` ran — or \`model: ""\` and no \`credential\` while the
|
||||
model choice is pending. Omit fields that are already stored and unchanged.
|
||||
4. \`finish_setup({ channels: [{ integrationType: "slack" }] })\` — include
|
||||
\`questions: [<model choice>]\` only if the model choice is pending; when
|
||||
the model is already set or \`resolve_llm\` resolved it in step 2, pass
|
||||
only the channel. For a
|
||||
model answer, call \`resolve_llm\` with it, then \`patch_config(...)\` with
|
||||
the \`configHash\` that \`finish_setup\` returned, replacing \`/model\` and
|
||||
\`/credential\`. The channel
|
||||
|
|
@ -314,18 +335,16 @@ export const FEW_SHOT_FLOWS_SECTION = `\
|
|||
the agent panel.
|
||||
|
||||
### New agent: "Use Anthropic via OpenRouter"
|
||||
1. \`write_todos\` with the plan.
|
||||
2. \`resolve_llm({ provider: "openrouter" })\`.
|
||||
3. \`agent-context({ type: "config" })\`.
|
||||
4. \`write_config(...)\` with \`model: "openrouter/{resolvedModel}"\`,
|
||||
1. \`resolve_llm({ provider: "openrouter" })\`.
|
||||
2. \`agent-context({ type: "config" })\`.
|
||||
3. \`write_config(...)\` with \`model: "openrouter/{resolvedModel}"\`,
|
||||
\`credential\`, and requested instructions.
|
||||
|
||||
### Change the existing model
|
||||
1. \`write_todos\` with the plan.
|
||||
2. \`ask_questions({ ... })\` for the new model choice, then
|
||||
1. \`ask_questions({ ... })\` for the new model choice, then
|
||||
\`resolve_llm({ provider, model })\`.
|
||||
3. \`agent-context({ type: "config" })\`.
|
||||
4. \`patch_config(...)\` replacing \`/model\` and \`/credential\`.
|
||||
2. \`agent-context({ type: "config" })\`.
|
||||
3. \`patch_config(...)\` replacing \`/model\` and \`/credential\`.
|
||||
|
||||
### Add an explicitly requested n8n node tool to an existing agent
|
||||
1. Load \`agent-builder-node-tools\`, then call \`search_nodes\` and
|
||||
|
|
|
|||
|
|
@ -38,10 +38,6 @@ import { getModelRecommendationsSection } from './agents-builder-model-recommend
|
|||
import { buildBuilderPrompt, buildBuilderSessionContext } from './agents-builder-prompts';
|
||||
import { AgentsBuilderToolsService, type BuilderTools } from './agents-builder-tools.service';
|
||||
import { BuilderCheckpointUnavailableError } from './errors';
|
||||
import {
|
||||
BUILDER_PLANNER_TODOS_DESCRIPTION,
|
||||
BUILDER_PLANNER_TODOS_SYSTEM_INSTRUCTION,
|
||||
} from './prompts/planner-todos.prompt';
|
||||
import { getBuilderRuntimeSkills } from './skills';
|
||||
import { N8NCheckpointStorage } from '../integrations/n8n-checkpoint-storage';
|
||||
import { N8nMemory } from '../integrations/n8n-memory';
|
||||
|
|
@ -376,16 +372,10 @@ export class AgentsBuilderService {
|
|||
agentId: string,
|
||||
session: InstanceAiBuilderSessionOptions,
|
||||
): Promise<void> {
|
||||
const { createPlannerTodosTool } = await import('@n8n/agents');
|
||||
const plannerTodosTool = createPlannerTodosTool({
|
||||
description: BUILDER_PLANNER_TODOS_DESCRIPTION,
|
||||
systemInstruction: BUILDER_PLANNER_TODOS_SYSTEM_INSTRUCTION,
|
||||
});
|
||||
const reportRequiredArtifactTool = await this.createRequiredArtifactTool(session);
|
||||
const builderTools = [
|
||||
...tools.json,
|
||||
...tools.shared,
|
||||
plannerTodosTool,
|
||||
...(reportRequiredArtifactTool ? [reportRequiredArtifactTool] : []),
|
||||
];
|
||||
const claimedToolNames = new Set(builderTools.map((tool) => tool.name));
|
||||
|
|
|
|||
|
|
@ -439,7 +439,7 @@ export function buildFinishSetupTool(deps: FinishSetupToolDeps): BuiltTool {
|
|||
'Collect everything still needed to finish the initial build in ONE guided flow: open ' +
|
||||
'questions (including the model choice), credential slots, and chat-channel ' +
|
||||
'setup. Call it at most once, only in the trailing step of an initial build ' +
|
||||
'when only blocked tasks remain, and never together with another interactive tool. ' +
|
||||
'when only pending setup remains, and never together with another interactive tool. ' +
|
||||
'It shows setup cards back-to-back without returning control between them: questions, ' +
|
||||
'then credentials, then one card per requested channel. Channel cards always run last ' +
|
||||
'after every credential phase, including when earlier setup was skipped or dismissed. Pass ' +
|
||||
|
|
|
|||
|
|
@ -49,14 +49,15 @@ During an initial build:
|
|||
\`credential\` omitted (skip verification), node tools with credential
|
||||
slots omitted. Leave Episodic Memory disabled while its credential is
|
||||
missing.
|
||||
- Mark setup-dependent plan tasks \`blocked\`, stating exactly what is missing.
|
||||
- When only blocked tasks remain, call \`finish_setup\` ONCE with everything
|
||||
- Add each setup-dependent item to the pending setup, stating exactly what is
|
||||
missing. Keep building everything that does not depend on it.
|
||||
- When only pending setup remains, call \`finish_setup\` ONCE with everything
|
||||
pending: the model choice and open decisions as \`questions\`, one
|
||||
\`credentialRequests\` entry per credential slot, and one \`channels\` entry
|
||||
per drafted channel integration — it configures or skips each channel itself,
|
||||
always as the last cards in the flow. Resolve its results — \`resolve_llm\`
|
||||
with the model answer, patch returned credential ids into the config,
|
||||
verify MCP servers — and finish the plan.
|
||||
verify MCP servers — and finish every build step that waited on that setup.
|
||||
- Do not call \`configure_channel\` again after \`finish_setup\` handles a channel card.
|
||||
- After \`finish_setup\`, end your reply with a short setup checklist for
|
||||
skipped or dismissed setup that remains unresolved — one line per item naming
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ Use this to resolve the target agent's main \`model\` and \`credential\`.
|
|||
2. If \`resolve_llm\` succeeds, persist \`model = "{provider}/{model}"\` and \`credential = credentialId\`. If the result has \`claimedFreeOpenAiCredits: true\`, tell the user you set them up with free OpenAI credits. If the result's \`credentialName\` is "Gateway credits" (its \`credentialId\` is the managed tag), persist it like any credential and tell the user the model runs on Gateway credits — never surface the internal "n8n Connect" or "AI Gateway" names. If it has \`autoPicked: true\`, tell the user which provider and model you picked and that they can ask to change it — do not ask for confirmation and do not raise a trailing model question.
|
||||
3. If the user asks to pick, change, confirm, or configure a model or main credential, ask via \`ask_questions\`; do not ask in prose.
|
||||
- Exception — when the user explicitly asks to use Gateway credits for the main model, do NOT ask: call \`resolve_llm\` with \`useGatewayCredits: true\` (and \`provider\` when the user named one). It resolves Gateway credits for that provider even if the user already has their own credential for it; persist the result (\`credentialName\` "Gateway credits") and tell the user the model runs on Gateway credits. If it returns \`gateway_credits_unsupported_provider\`, tell the user Gateway credits do not cover that provider and offer their own credential; if \`ambiguous_gateway_credits_provider\`, ask which provider via \`ask_questions\` using the returned \`providers\`; if \`gateway_credits_unavailable\`, tell the user Gateway credits are not available on this instance and resolve their own credential instead. On \`unknown_model\`, retry with a value from the returned \`availableModels\` or surface those options.
|
||||
4. During an initial build, if \`resolve_llm\` reports missing or ambiguous credentials/provider, do not ask: mark the model task \`blocked\`, keep building with \`model: ""\` and no \`credential\`, and include the model choice as a question in the trailing \`finish_setup\` call — for ambiguity between multiple credentials of one provider, use the credential names from the resolve_llm result as the question's options — when it resolves, call \`resolve_llm\` with the answer (pass \`credentialId\` when the user picked a specific credential) and patch \`/model\` and \`/credential\` — base the patch on the \`config\` and \`configHash\` that \`finish_setup\` returned, and check that config first, since the user may have already set the model in the panel. For a model change on an existing agent, ask immediately instead, and never write \`model: ""\` over an existing model — keep the current model and credential until the new one is resolved.
|
||||
4. During an initial build, if \`resolve_llm\` reports missing or ambiguous credentials/provider, do not ask: add the model choice to the pending setup, keep building with \`model: ""\` and no \`credential\`, and include the model choice as a question in the trailing \`finish_setup\` call — for ambiguity between multiple credentials of one provider, use the credential names from the resolve_llm result as the question's options — when it resolves, call \`resolve_llm\` with the answer (pass \`credentialId\` when the user picked a specific credential) and patch \`/model\` and \`/credential\` — base the patch on the \`config\` and \`configHash\` that \`finish_setup\` returned, and check that config first, since the user may have already set the model in the panel. For a model change on an existing agent, ask immediately instead, and never write \`model: ""\` over an existing model — keep the current model and credential until the new one is resolved.
|
||||
5. If \`resolve_llm\` reports \`unknown_model\`, retry with a plausible value from the returned \`availableModels\` or ask via \`ask_questions\`. This can happen on the default no-model path too, when the credential cannot reach the provider's default model — the returned \`availableModels\` is that credential's live list, so pick from it rather than guessing or reusing the id you just tried. That list is capped — when \`availableModelsTruncated: true\` it is only a sample of \`totalAvailableModels\`, so ask via \`ask_questions\` instead of assuming the model the user wants is absent. If it reports \`model_lookup_failed\` (the provider's model list could not be fetched, e.g. a transient error — possible even on the default no-model path), retry \`resolve_llm\`; do not guess a model.
|
||||
6. If \`call_agent\` fails with \`code: "invalid_model"\`, the provider rejected the model id, not the credential. Do not tell the user to check, revoke, or regenerate their API key. Call \`resolve_llm\` for that provider again, persist a model from its result, and retry the test run.
|
||||
7. If the model is still unresolved when the user asks to run or publish the agent, leave the draft with \`model: ""\`, do not guess a model, and tell the user the agent needs a model and credential first — in the panel or here in chat. If they dismiss a model-change question on an existing agent, keep the current model and credential unchanged.
|
||||
|
|
|
|||
|
|
@ -1,26 +0,0 @@
|
|||
/**
|
||||
* Builder-specific model-visible text for the SDK's `createPlannerTodosTool`.
|
||||
* The SDK ships domain-neutral defaults; these strings keep the agent
|
||||
* builder's `write_todos` tool description/instructions unchanged from
|
||||
* before the SDK text was made generic.
|
||||
*/
|
||||
export const BUILDER_PLANNER_TODOS_DESCRIPTION =
|
||||
'Create or update a structured task list for the current build. Use it to decompose the work, ' +
|
||||
'track progress, and record which tasks are blocked on user input. Use it for every build or ' +
|
||||
'change request. This tool only updates the task list; it does not perform work or ask the user.';
|
||||
|
||||
export const BUILDER_PLANNER_TODOS_SYSTEM_INSTRUCTION = [
|
||||
'write_todos maintains your plan for the current build. It never asks the user or performs work itself.',
|
||||
'WHEN TO USE write_todos:',
|
||||
'- Every request that builds or changes the agent, before other tool calls.',
|
||||
'- You need to track progress or record tasks blocked on user input.',
|
||||
'WHEN NOT TO USE write_todos:',
|
||||
'- Purely conversational replies with no build work.',
|
||||
'HOW TO USE write_todos:',
|
||||
'- Write concrete, self-contained tasks; mark the first active task in_progress immediately.',
|
||||
'- Mark a task blocked when it cannot proceed without user input, and state exactly what input is missing in the task content.',
|
||||
'- Marking a task blocked IS the action for now. Do not ask the user about it while any non-blocked task remains; continue with unblocked tasks.',
|
||||
'- When only blocked tasks remain: during an initial build, follow the Initial Build rules (call finish_setup); otherwise end your turn with a summary of what is missing, and unblock and finish the tasks in later turns as the user provides input.',
|
||||
'- Update task status as soon as work completes; do not batch completions at the end.',
|
||||
'- Do not call write_todos multiple times in parallel; send one full list update at a time.',
|
||||
].join('\n');
|
||||
|
|
@ -133,10 +133,13 @@ The \`integrations\` array controls how the target agent is triggered.
|
|||
agent; do not follow up with \`patch_config\`/\`write_config\` to write the
|
||||
credential.
|
||||
- ${INITIAL_BUILD_NOTE} Instead of \`configure_channel\`: after
|
||||
\`agent-context({ type: "integrations" })\` returns the matching type,
|
||||
\`patch_config\` (with the \`configHash\` from your latest config read or write) adding \`{ "type": "<integrationType>", "credentialId": "" }\`
|
||||
to \`/integrations/-\` (include a minimal valid draft \`settings\` object for
|
||||
telegram) so the channel appears in the agent panel as needing setup. Pass
|
||||
\`agent-context({ type: "integrations" })\` returns the matching type, add
|
||||
\`{ "type": "<integrationType>", "credentialId": "" }\` to \`integrations\`
|
||||
in your single initial config write (include a minimal valid draft
|
||||
\`settings\` object for telegram) so the channel appears in the agent panel
|
||||
as needing setup. If the config is already written, \`patch_config\` (with
|
||||
the \`configHash\` from your latest config read or write) adding it to
|
||||
\`/integrations/-\` instead. Pass
|
||||
the same \`integrationType\` in the trailing \`finish_setup\` call's
|
||||
\`channels\` array — its card configures or skips the channel itself. Do not
|
||||
call \`configure_channel\` again after \`finish_setup\` handles the card. If
|
||||
|
|
@ -227,8 +230,10 @@ Follow these steps for the selected MCP result:
|
|||
credential is already persisted.
|
||||
|
||||
${INITIAL_BUILD_NOTE} For MCP that means: pick the best candidate as an
|
||||
assumption (above), then \`patch_config\` (with the \`configHash\` from your latest config read or write) a draft
|
||||
\`/mcpServers/-\` entry using \`name\`, \`url\`, \`transport\`,
|
||||
assumption (above), then add a draft \`mcpServers\` entry to your single
|
||||
initial config write (or \`patch_config\` it to \`/mcpServers/-\`, with the
|
||||
\`configHash\` from your latest config read or write, if the config is
|
||||
already written) using \`name\`, \`url\`, \`transport\`,
|
||||
\`authentication\`, and \`metadata.nodeTypeName\` from \`selectedResult\` with
|
||||
\`credential\` omitted, and skip \`verify_mcp_server\` — there is nothing to
|
||||
authenticate yet. Include the credential in the trailing \`finish_setup\` call;
|
||||
|
|
|
|||
|
|
@ -48,8 +48,8 @@ specific-page fetching, use only \`n8n-nodes-base.httpRequestTool\`.
|
|||
|
||||
Use only an exact URL explicitly supplied by the user for
|
||||
\`n8n-nodes-base.httpRequestTool\`. If the user has not supplied one, you MUST
|
||||
ask which URL the tool should fetch. During an initial build, mark this setup
|
||||
as blocked and include the URL question in the single trailing \`finish_setup\`
|
||||
ask which URL the tool should fetch. During an initial build, add this to the
|
||||
pending setup and include the URL question in the single trailing \`finish_setup\`
|
||||
call; add the tool with the returned URL after the user answers. On later
|
||||
turns, call \`${ASK_QUESTIONS_TOOL_NAME}\` and wait for the answer before
|
||||
mutating the config. Do not search for, derive, infer, guess, or invent a URL
|
||||
|
|
|
|||
|
|
@ -68,9 +68,9 @@ applicable sections are filled with real content (the actual steps, rules,
|
|||
examples, and edge cases). Derive missing domain detail from the user's
|
||||
stated goal as stated assumptions, and list them in your summary. Use
|
||||
\`ask_questions\` only when even a reasonable assumption is impossible — never
|
||||
during an initial build: mark the task \`blocked\` instead, per the Initial
|
||||
Build rules in your system prompt. Never create a placeholder or vague
|
||||
skill.
|
||||
during an initial build: add the open decision to the pending setup
|
||||
instead, per the Initial Build rules in your system prompt. Never create a
|
||||
placeholder or vague skill.
|
||||
|
||||
## Workflow
|
||||
|
||||
|
|
|
|||
|
|
@ -74,9 +74,9 @@ BOTH of these are true for it:
|
|||
as an assumption.
|
||||
|
||||
Use \`ask_questions\` only when even a reasonable assumption is impossible —
|
||||
never during an initial build: mark the task \`blocked\` instead, per the
|
||||
Initial Build rules in your system prompt. Never create a placeholder or
|
||||
"refine-it-later" task.
|
||||
never during an initial build: add the open decision to the pending setup
|
||||
instead, per the Initial Build rules in your system prompt. Never create a
|
||||
placeholder or "refine-it-later" task.
|
||||
|
||||
## Workflow
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user