NebulaFlow integrates with Large Language Models (LLMs) via the Amp SDK and OpenRouter SDK. This guide covers configuration, usage, and best practices for LLM nodes.
The Amp SDK is the primary LLM provider for NebulaFlow.
Features:
Requirements:
OpenRouter SDK provides access to multiple LLM providers through a single API.
Features:
Requirements:
export AMP_API_KEY="your_amp_api_key_here"
Required: Yes (for LLM nodes)
How to get:
export OPENROUTER_API_KEY="your_openrouter_api_key_here"
Required: No (optional)
How to get:
Create .nebulaflow/settings.json in your workspace root:
{
"nebulaflow": {
"settings": {
"amp.dangerouslyAllowAll": false,
"amp.experimental.commandApproval.enabled": true,
"amp.commands.allowlist": ["git", "npm", "node"],
"amp.commands.strict": true,
"internal.primaryModel": "openrouter/anthropic/claude-3-5-sonnet",
"openrouter.key": "sk-or-...",
"openrouter.models": [
{
"model": "openrouter/anthropic/claude-3-5-sonnet",
"provider": "anthropic",
"maxOutputTokens": 4096,
"contextWindow": 200000
},
{
"model": "openrouter/openai/gpt-5.2-codex",
"provider": "openai",
"maxOutputTokens": 8192,
"contextWindow": 128000
}
]
}
}
}
The Amp SDK supports various settings that can be configured:
| Setting | Type | Description | Default |
|---|---|---|---|
amp.dangerouslyAllowAll |
boolean | Bypass safety checks | false |
amp.experimental.commandApproval.enabled |
boolean | Enable command approval | true |
amp.commands.allowlist |
string[] | Allowed commands | [] |
amp.commands.strict |
boolean | Strict command validation | true |
internal.primaryModel |
string | Default model ID | - |
openrouter.models |
array | OpenRouter model configs | [] |
Configure OpenRouter models in workspace settings:
{
"nebulaflow": {
"settings": {
"openrouter.models": [
{
"model": "openrouter/anthropic/claude-3-5-sonnet",
"provider": "anthropic",
"maxOutputTokens": 4096,
"contextWindow": 200000,
"isReasoning": false,
"reasoning_effort": "medium"
},
{
"model": "openrouter/openai/gpt-5.2-codex",
"provider": "openai",
"maxOutputTokens": 8192,
"contextWindow": 128000,
"isReasoning": true,
"reasoning_effort": "high"
}
]
}
}
}
Configuration options:
model: Full model IDprovider: Provider name (for routing)maxOutputTokens: Maximum tokens to generatecontextWindow: Context window sizeisReasoning: Whether model supports reasoningreasoning_effort: Default reasoning effort levelinterface LLMNode {
type: NodeType.LLM
data: {
title: string
content: string // Prompt template
active: boolean
model: { id: string; title?: string }
reasoningEffort?: 'minimal' | 'low' | 'medium' | 'high'
systemPromptTemplate?: string
disabledTools?: string[]
timeoutSec?: number
dangerouslyAllowAll?: boolean
attachments?: AttachmentRef[]
}
}
{
type: NodeType.LLM,
data: {
title: 'Simple Query',
content: 'What is the capital of France?',
active: true,
model: { id: 'openrouter/anthropic/claude-3-5-sonnet' }
}
}
{
type: NodeType.LLM,
data: {
title: 'Process User Input',
content: 'Analyze the following text and provide a summary: ${1}',
active: true,
model: { id: 'openrouter/openai/gpt-4o' },
reasoningEffort: 'medium'
}
}
{
type: NodeType.LLM,
data: {
title: 'Code Review Agent',
content: 'Review this code: ${1}',
active: true,
model: { id: 'openrouter/anthropic/claude-3-5-sonnet' },
systemPromptTemplate: 'You are a senior software engineer with 10+ years of experience. Provide detailed, constructive feedback on code quality, security, and best practices.'
}
}
{
type: NodeType.LLM,
data: {
title: 'Safe Assistant',
content: 'Answer this question: ${1}',
active: true,
model: { id: 'openrouter/anthropic/claude-3-5-sonnet' },
disabledTools: ['bash', 'filesystem', 'network'],
dangerouslyAllowAll: false
}
}
{
type: NodeType.LLM,
data: {
title: 'Image Analysis',
content: 'Describe what you see in this image',
active: true,
model: { id: 'openrouter/openai/gpt-4o' },
attachments: [
{
id: 'image1',
kind: 'image',
source: 'file',
path: '/path/to/diagram.png',
altText: 'Architecture diagram'
}
]
}
}
Models are loaded from two sources:
Amp SDK models:
gpt-4ogpt-4o-miniclaude-3-5-sonnetOpenRouter models:
openrouter/anthropic/claude-3-5-sonnetopenrouter/openai/gpt-4oopenrouter/google/gemini-proThe selected model ID is normalized via the Amp SDK’s resolveModel function. If resolution fails, the raw ID is used.
Use template variables to reference upstream node outputs:
# Basic variable reference
"Process this: ${1}"
# Multiple variables
"Analyze ${1} and summarize: ${2}"
# Named variables (if using Variable nodes)
"User query: ${userQuery}"
Set a system prompt to guide model behavior:
{
data: {
systemPromptTemplate: 'You are a helpful assistant specialized in technical documentation.'
}
}
Reasoning effort controls how much computational effort the model uses to generate responses.
{
data: {
reasoningEffort: 'high' // Use for complex tasks
}
}
minimal:
low:
medium:
high:
Tool calling allows LLMs to invoke external functions or tools.
Tools are automatically resolved via the Amp SDK:
// Tools are normalized to official names
disabledTools: ['bash', 'filesystem'] // Normalized to official tool names
Prevent certain capabilities:
{
data: {
disabledTools: ['bash', 'filesystem', 'network']
}
}
Common tools:
bash - Shell command executionfilesystem - File system accessnetwork - Network requestscode_execution - Code executionAttachments allow LLMs to process images and other media.
Images:
{
attachments: [
{
id: 'image1',
kind: 'image',
source: 'file',
path: '/path/to/image.png',
altText: 'Description of image'
}
]
}
URL-based images:
{
attachments: [
{
id: 'image2',
kind: 'image',
source: 'url',
url: 'https://example.com/image.png',
altText: 'Description of image'
}
]
}
LLM nodes maintain conversation history for multi-turn interactions.
// LLM node automatically maintains history
// No special configuration needed
Thread IDs are stored per node:
Example workflow:
LLM Node (Thread A) → LLM Node (Thread A) → LLM Node (Thread B)
LLM nodes stream responses in real-time:
// Events received during execution
{
type: 'node_assistant_content',
data: {
nodeId: 'llm-node-1',
threadID: 'thread-abc-123',
content: [
{ type: 'text', text: 'Hello' },
{ type: 'thinking', thinking: 'I need to respond...' }
]
}
}
Common errors:
AMP_API_KEY not set - Set environment variableModel not found - Check model IDRate limit exceeded - Wait and retryNetwork error - Check connectivityMonitor token counts:
// Token count events
{
type: 'token_count',
data: {
count: 150,
nodeId: 'llm-node-1'
}
}
Optimization tips:
Choose the right model:
Implement caching:
Never commit API keys:
# Good: Environment variables
export AMP_API_KEY="your_key"
# Bad: Hardcoded in workflows
# content: "Use key: sk-..."
Use Amp safety features:
{
data: {
dangerouslyAllowAll: false, // Keep false for safety
disabledTools: ['bash', 'filesystem'] // Disable dangerous tools
}
}
Be aware of:
Cause: SDK not properly linked
Solution:
npm i /home/prinova/CodeProjects/upstreamAmp/sdk
Cause: Environment variable missing
Solution:
export AMP_API_KEY="your_amp_api_key_here"
Cause: Model ID incorrect or not available
Solution:
Cause: Too many API requests
Solution:
Cause: Request taking too long
Solution:
Enable debug logging:
// Extension logs show:
// - API requests
// - Model resolution
// - Error details
Check events:
node_assistant_content - Streaming responsestoken_count - Token usagenode_execution_status - Execution statusText Node (query)
└── LLM Node (answer query)
└── Preview Node (display result)
Text Node (input)
└── LLM Node (analyze)
└── LLM Node (summarize)
└── Preview Node (final result)
Text Node (input)
└── IF Node (check condition)
├── True: LLM Node (process A)
└── False: LLM Node (process B)
└── Preview Node (combine results)
Loop Start (iterations=5)
└── LLM Node (process item ${i})
Loop End
└── Accumulator Node (collect results)
Text Node (query)
├── LLM Node (Model A)
├── LLM Node (Model B)
└── Accumulator Node (compare responses)
dangerouslyAllowAll false{
data: {
systemPromptTemplate: `You are a specialized assistant with the following capabilities:
1. Code analysis and review
2. Documentation generation
3. Technical writing
4. Bug identification
Please provide detailed, actionable feedback.`
}
}
{
data: {
timeoutSec: 300 // 5 minutes
}
}
{
data: {
dangerouslyAllowAll: true, // Bypasses safety checks
disabledTools: [] // Enable all tools
}
}
Warning: Only use in trusted environments.