mirror of
https://github.com/simstudioai/sim.git
synced 2026-01-09 23:17:59 -05:00
improvement(copilot): add best practices for core blocks (#1427)
* improvement(copilot): add best practices for blocks * fix kb, api * Update apps/sim/blocks/blocks/memory.ts Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> * address comments * remove non deterministic test --------- Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
dd8f633f9f
commit
fbb164db98
@@ -179,30 +179,6 @@ describe('Workflow Variables API Route', () => {
|
||||
expect(response.headers.get('Cache-Control')).toBe('max-age=30, stale-while-revalidate=300')
|
||||
expect(response.headers.get('ETag')).toMatch(/^"variables-workflow-123-\d+"$/)
|
||||
})
|
||||
|
||||
it.concurrent('should return empty object for workflows with no variables', async () => {
|
||||
const mockWorkflow = {
|
||||
id: 'workflow-123',
|
||||
userId: 'user-123',
|
||||
workspaceId: null,
|
||||
variables: null,
|
||||
}
|
||||
|
||||
authMocks.setAuthenticated({ id: 'user-123', email: 'test@example.com' })
|
||||
databaseMocks = createMockDatabase({
|
||||
select: { results: [[mockWorkflow]] },
|
||||
})
|
||||
|
||||
const req = new NextRequest('http://localhost:3000/api/workflows/workflow-123/variables')
|
||||
const params = Promise.resolve({ id: 'workflow-123' })
|
||||
|
||||
const { GET } = await import('@/app/api/workflows/[id]/variables/route')
|
||||
const response = await GET(req, { params })
|
||||
|
||||
expect(response.status).toBe(200)
|
||||
const data = await response.json()
|
||||
expect(data.data).toEqual({})
|
||||
})
|
||||
})
|
||||
|
||||
describe('POST /api/workflows/[id]/variables', () => {
|
||||
|
||||
@@ -65,6 +65,11 @@ export const AgentBlock: BlockConfig<AgentResponse> = {
|
||||
authMode: AuthMode.ApiKey,
|
||||
longDescription:
|
||||
'The Agent block is a core workflow block that is a wrapper around an LLM. It takes in system/user prompts and calls an LLM provider. It can also make tool calls by directly containing tools inside of its tool input. It can additionally return structured output.',
|
||||
bestPractices: `
|
||||
- Cannot use core blocks like API, Webhook, Function, Workflow, Memory as tools. Only integrations or custom tools.
|
||||
- Check custom tools examples for YAML syntax. Only construct these if there isn't an existing integration for that purpose.
|
||||
- Response Format should be a valid JSON Schema. This determines the output of the agent only if present. Fields can be accessed at root level by the following blocks: e.g. <agent1.field>. If response format is not present, the agent will return the standard outputs: content, model, tokens, toolCalls.
|
||||
`,
|
||||
docsLink: 'https://docs.sim.ai/blocks/agent',
|
||||
category: 'blocks',
|
||||
bgColor: 'var(--brand-primary-hex)',
|
||||
|
||||
@@ -9,6 +9,9 @@ export const ApiBlock: BlockConfig<RequestResponse> = {
|
||||
longDescription:
|
||||
'This is a core workflow block. Connect to any external API with support for all standard HTTP methods and customizable request parameters. Configure headers, query parameters, and request bodies. Standard headers (User-Agent, Accept, Cache-Control, etc.) are automatically included.',
|
||||
docsLink: 'https://docs.sim.ai/blocks/api',
|
||||
bestPractices: `
|
||||
- Curl the endpoint yourself before filling out the API block to make sure it's working IF you have the necessary authentication headers. Clarify with the user if you need any additional headers.
|
||||
`,
|
||||
category: 'blocks',
|
||||
bgColor: '#2F55FF',
|
||||
icon: ApiIcon,
|
||||
|
||||
@@ -7,6 +7,11 @@ export const ApiTriggerBlock: BlockConfig = {
|
||||
description: 'Expose as HTTP API endpoint',
|
||||
longDescription:
|
||||
'API trigger to start the workflow via authenticated HTTP calls with structured input.',
|
||||
bestPractices: `
|
||||
- Can run the workflow manually to test implementation when this is the trigger point.
|
||||
- The input format determines variables accesssible in the following blocks. E.g. <api1.paramName>. You can set the value in the input format to test the workflow manually.
|
||||
- In production, the curl would come in as e.g. curl -X POST -H "X-API-Key: $SIM_API_KEY" -H "Content-Type: application/json" -d '{"paramName":"example"}' https://www.staging.sim.ai/api/workflows/9e7e4f26-fc5e-4659-b270-7ea474b14f4a/execute -- If user asks to test via API, you might need to clarify the API key.
|
||||
`,
|
||||
category: 'triggers',
|
||||
bgColor: '#2F55FF',
|
||||
icon: ApiIcon,
|
||||
|
||||
@@ -10,6 +10,9 @@ export const ChatTriggerBlock: BlockConfig = {
|
||||
name: 'Chat',
|
||||
description: 'Start workflow from a chat deployment',
|
||||
longDescription: 'Chat trigger to run the workflow via deployed chat interfaces.',
|
||||
bestPractices: `
|
||||
- Can run the workflow manually to test implementation when this is the trigger point by passing in a message.
|
||||
`,
|
||||
category: 'triggers',
|
||||
bgColor: '#6F3DFA',
|
||||
icon: ChatTriggerIcon,
|
||||
|
||||
@@ -21,6 +21,10 @@ export const ConditionBlock: BlockConfig<ConditionBlockOutput> = {
|
||||
description: 'Add a condition',
|
||||
longDescription:
|
||||
'This is a core workflow block. Add a condition to the workflow to branch the execution path based on a boolean expression.',
|
||||
bestPractices: `
|
||||
- Write the conditions using standard javascript syntax except referencing the outputs of previous blocks using <> syntax, and keep them as simple as possible. No hacky fallbacks.
|
||||
- Can reference workflow variables using <blockName.output> syntax as usual within conditions.
|
||||
`,
|
||||
docsLink: 'https://docs.sim.ai/blocks/condition',
|
||||
bgColor: '#FF752F',
|
||||
icon: ConditionalIcon,
|
||||
|
||||
@@ -10,6 +10,9 @@ export const FileBlock: BlockConfig<FileParserOutput> = {
|
||||
name: 'File',
|
||||
description: 'Read and parse multiple files',
|
||||
longDescription: `Integrate File into the workflow. Can upload a file manually or insert a file url.`,
|
||||
bestPractices: `
|
||||
- You should always use the File URL input method and enter the file URL if the user gives it to you or clarify if they have one.
|
||||
`,
|
||||
docsLink: 'https://docs.sim.ai/tools/file',
|
||||
category: 'tools',
|
||||
bgColor: '#40916C',
|
||||
|
||||
@@ -9,6 +9,12 @@ export const FunctionBlock: BlockConfig<CodeExecutionOutput> = {
|
||||
description: 'Run custom logic',
|
||||
longDescription:
|
||||
'This is a core workflow block. Execute custom JavaScript or Python code within your workflow. Use E2B for remote execution with imports or enable Fast Mode (bolt) to run JavaScript locally for lowest latency.',
|
||||
bestPractices: `
|
||||
- If the user asks for Python, you should always use the Remote Code Execution switch and select Python.
|
||||
- If the user asks Javascript and you need imports, you should use the Remote Code Execution switch and select Javascript.
|
||||
- If the user asks for a simple function, don't turn on the Remote Code Execution switch and write it in javascript.
|
||||
- Can reference workflow variables using <blockName.output> syntax as usual within code. Avoid XML/HTML tags.
|
||||
`,
|
||||
docsLink: 'https://docs.sim.ai/blocks/function',
|
||||
category: 'blocks',
|
||||
bgColor: '#FF402F',
|
||||
@@ -44,7 +50,7 @@ export const FunctionBlock: BlockConfig<CodeExecutionOutput> = {
|
||||
enabled: true,
|
||||
maintainHistory: true,
|
||||
prompt: `You are an expert JavaScript programmer.
|
||||
Generate ONLY the raw body of a JavaScript function based on the user's request.
|
||||
Generate ONLY the raw body of a JavaScript function based on the user's request. Never wrap in markdown formatting.
|
||||
The code should be executable within an 'async function(params, environmentVariables) {...}' context.
|
||||
- 'params' (object): Contains input parameters derived from the JSON schema. Access these directly using the parameter name wrapped in angle brackets, e.g., '<paramName>'. Do NOT use 'params.paramName'.
|
||||
- 'environmentVariables' (object): Contains environment variables. Reference these using the double curly brace syntax: '{{ENV_VAR_NAME}}'. Do NOT use 'environmentVariables.VAR_NAME' or env.
|
||||
|
||||
@@ -13,7 +13,11 @@ export const GenericWebhookBlock: BlockConfig = {
|
||||
icon: WebhookIcon,
|
||||
bgColor: '#10B981', // Green color for triggers
|
||||
triggerAllowed: true,
|
||||
|
||||
bestPractices: `
|
||||
- You can test the webhook by sending a request to the webhook URL. E.g. depending on authorization: curl -X POST http://localhost:3000/api/webhooks/trigger/d8abcf0d-1ee5-4b77-bb07-b1e8142ea4e9 -H "Content-Type: application/json" -H "X-Sim-Secret: 1234" -d '{"message": "Test webhook trigger", "data": {"key": "v"}}'
|
||||
- Continuing example above, the body can be accessed in downstream block using dot notation. E.g. <webhook1.message> and <webhook1.data.key>
|
||||
- Only use when there's no existing integration for the service with triggerAllowed flag set to true.
|
||||
`,
|
||||
subBlocks: [
|
||||
// Generic webhook configuration - always visible
|
||||
{
|
||||
|
||||
@@ -11,6 +11,11 @@ export const InputTriggerBlock: BlockConfig = {
|
||||
description: 'Start workflow manually with a defined input schema',
|
||||
longDescription:
|
||||
'Manually trigger the workflow from the editor with a structured input schema. This enables typed inputs for parent workflows to map into.',
|
||||
bestPractices: `
|
||||
- Can run the workflow manually to test implementation when this is the trigger point.
|
||||
- The input format determines variables accesssible in the following blocks. E.g. <input1.paramName>. You can set the value in the input format to test the workflow manually.
|
||||
- Also used in child workflows to map variables from the parent workflow.
|
||||
`,
|
||||
category: 'triggers',
|
||||
bgColor: '#3B82F6',
|
||||
icon: InputTriggerIcon,
|
||||
|
||||
@@ -7,6 +7,10 @@ export const KnowledgeBlock: BlockConfig = {
|
||||
description: 'Use vector search',
|
||||
longDescription:
|
||||
'Integrate Knowledge into the workflow. Can search, upload chunks, and create documents.',
|
||||
bestPractices: `
|
||||
- Search up examples with knowledge base blocks to understand YAML syntax.
|
||||
- Clarify which tags are available for the knowledge base to understand whether to use tag filters on a search.
|
||||
`,
|
||||
bgColor: '#00B0B0',
|
||||
icon: PackageSearchIcon,
|
||||
category: 'blocks',
|
||||
|
||||
@@ -8,6 +8,11 @@ export const MemoryBlock: BlockConfig = {
|
||||
longDescription:
|
||||
'Integrate Memory into the workflow. Can add, get a memory, get all memories, and delete memories.',
|
||||
bgColor: '#F64F9E',
|
||||
bestPractices: `
|
||||
- Do not use this block unless the user explicitly asks for it.
|
||||
- Search up examples with memory blocks to understand YAML syntax.
|
||||
- Used in conjunction with agent blocks to persist messages between runs. User messages should be added with role 'user' and assistant messages should be added with role 'assistant' with the agent sandwiched between.
|
||||
`,
|
||||
icon: BrainIcon,
|
||||
category: 'blocks',
|
||||
docsLink: 'https://docs.sim.ai/tools/memory',
|
||||
|
||||
@@ -9,6 +9,11 @@ export const ResponseBlock: BlockConfig<ResponseBlockOutput> = {
|
||||
longDescription:
|
||||
'Integrate Response into the workflow. Can send build or edit structured responses into a final workflow response.',
|
||||
docsLink: 'https://docs.sim.ai/blocks/response',
|
||||
bestPractices: `
|
||||
- Only use this if the trigger block is the API Trigger.
|
||||
- Prefer the editor mode over the builder mode.
|
||||
- This is usually used as the last block in the workflow.
|
||||
`,
|
||||
category: 'blocks',
|
||||
bgColor: '#2F55FF',
|
||||
icon: ResponseIcon,
|
||||
|
||||
@@ -111,6 +111,10 @@ export const RouterBlock: BlockConfig<RouterResponse> = {
|
||||
authMode: AuthMode.ApiKey,
|
||||
longDescription:
|
||||
'This is a core workflow block. Intelligently direct workflow execution to different paths based on input analysis. Use natural language to instruct the router to route to certain blocks based on the input.',
|
||||
bestPractices: `
|
||||
- For the prompt, make it almost programmatic. Use the system prompt to define the routing criteria. Should be very specific with no ambiguity.
|
||||
- Use the target block *names* to define the routing criteria.
|
||||
`,
|
||||
category: 'blocks',
|
||||
bgColor: '#28C43F',
|
||||
icon: ConnectIcon,
|
||||
|
||||
@@ -11,6 +11,11 @@ export const ScheduleBlock: BlockConfig = {
|
||||
description: 'Trigger workflow execution on a schedule',
|
||||
longDescription:
|
||||
'Integrate Schedule into the workflow. Can trigger a workflow on a schedule configuration.',
|
||||
bestPractices: `
|
||||
- Search up examples with schedule blocks to understand YAML syntax.
|
||||
- Prefer the custom cron expression input method over the other schedule configuration methods.
|
||||
- Clarify the timezone if the user doesn't specify it.
|
||||
`,
|
||||
category: 'triggers',
|
||||
bgColor: '#6366F1',
|
||||
icon: ScheduleIcon,
|
||||
|
||||
@@ -20,6 +20,11 @@ export const WorkflowInputBlock: BlockConfig = {
|
||||
type: 'workflow_input',
|
||||
name: 'Workflow',
|
||||
description: 'Execute another workflow and map variables to its Input Trigger schema.',
|
||||
longDescription: `Execute another child workflow and map variables to its Input Trigger schema. Helps with modularizing workflows.`,
|
||||
bestPractices: `
|
||||
- Usually clarify/check if the user has tagged a workflow to use as the child workflow. Understand the child workflow to determine the logical position of this block in the workflow.
|
||||
- Remember, that the start point of the child workflow is the Input Form Trigger block.
|
||||
`,
|
||||
category: 'blocks',
|
||||
bgColor: '#6366F1', // Indigo - modern and professional
|
||||
icon: WorkflowIcon,
|
||||
|
||||
@@ -190,6 +190,7 @@ export interface BlockConfig<T extends ToolResponse = ToolResponse> {
|
||||
description: string
|
||||
category: BlockCategory
|
||||
longDescription?: string
|
||||
bestPractices?: string
|
||||
docsLink?: string
|
||||
bgColor: string
|
||||
icon: BlockIcon
|
||||
|
||||
@@ -37,6 +37,7 @@ export interface CopilotBlockMetadata {
|
||||
id: string
|
||||
name: string
|
||||
description: string
|
||||
bestPractices?: string
|
||||
commonParameters: Record<string, any>
|
||||
triggerAllowed?: boolean
|
||||
authType?: 'OAuth' | 'API Key' | 'Bot Token'
|
||||
@@ -157,6 +158,7 @@ export const getBlocksMetadataServerTool: BaseServerTool<
|
||||
id: blockId,
|
||||
name: blockConfig.name || blockId,
|
||||
description: blockConfig.longDescription || blockConfig.description || '',
|
||||
bestPractices: blockConfig.bestPractices,
|
||||
commonParameters: blockInputs,
|
||||
triggerAllowed: !!blockConfig.triggerAllowed,
|
||||
authType: resolveAuthType(blockConfig.authMode),
|
||||
@@ -362,6 +364,14 @@ const SPECIAL_BLOCKS_METADATA: Record<string, any> = {
|
||||
id: 'loop',
|
||||
name: 'Loop',
|
||||
description: 'Control flow block for iterating over collections or repeating actions',
|
||||
longDescription:
|
||||
'Control flow block for iterating over collections or repeating actions serially',
|
||||
bestPractices: `
|
||||
- Set reasonable limits for iterations.
|
||||
- Use forEach for collection processing, for loops for fixed iterations.
|
||||
- Cannot have loops/parallels inside a loop block.
|
||||
- For yaml it needs to connect blocks inside to the start field of the block.
|
||||
`,
|
||||
inputs: {
|
||||
loopType: { type: 'string', required: true, enum: ['for', 'forEach'] },
|
||||
iterations: { type: 'number', required: false, minimum: 1, maximum: 1000 },
|
||||
@@ -416,6 +426,13 @@ const SPECIAL_BLOCKS_METADATA: Record<string, any> = {
|
||||
id: 'parallel',
|
||||
name: 'Parallel',
|
||||
description: 'Control flow block for executing multiple branches simultaneously',
|
||||
longDescription: 'Control flow block for executing multiple branches simultaneously',
|
||||
bestPractices: `
|
||||
- Keep structures inside simple. Cannot have multiple blocks within a parallel block.
|
||||
- Cannot have loops/parallels inside a parallel block.
|
||||
- Agent block combobox can be <parallel.currentItem> if the user wants to query multiple models in parallel. The collection has to be an array of correct model strings available for the agent block.
|
||||
- For yaml it needs to connect blocks inside to the start field of the block.
|
||||
`,
|
||||
inputs: {
|
||||
parallelType: { type: 'string', required: true, enum: ['count', 'collection'] },
|
||||
count: { type: 'number', required: false, minimum: 1, maximum: 100 },
|
||||
|
||||
Reference in New Issue
Block a user