10 KiB
phase, plan, type, wave, depends_on, files_modified, autonomous, user_setup, must_haves
| phase | plan | type | wave | depends_on | files_modified | autonomous | user_setup | must_haves | |||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 04-logs-intelligence | 02 | execute | 1 |
|
false |
|
|
Purpose: Enables conversational interaction (REQ-08) by understanding user intent before execution. Users can speak naturally instead of memorizing command syntax.
Output: Extended n8n workflow with Claude API integration, intent parsing, and routing logic.
<execution_context> @/home/luc/.claude/get-shit-done/workflows/execute-plan.md @/home/luc/.claude/get-shit-done/templates/summary.md </execution_context>
@.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md @.planning/phases/04-logs-intelligence/04-RESEARCH.md @n8n-workflow.json Task 1: Add Claude API credential and HTTP Request node n8n-workflow.json Create Claude API integration in the workflow.- Add "Claude Intent Parser" HTTP Request node:
- Method: POST
- URL: https://api.anthropic.com/v1/messages
- Authentication: Header Auth
- Header: x-api-key = {{$credentials.anthropicApi.apiKey}} (or use Generic Credential)
- Header: anthropic-version = 2023-06-01
- Header: content-type = application/json
- Body (JSON):
{ "model": "claude-sonnet-4-5-20250929", "max_tokens": 256, "system": [ { "type": "text", "text": "You are a Docker container management assistant. Parse user requests and return ONLY valid JSON.\n\nValid actions:\n- view_logs: User wants to see container logs\n- query_stats: User asks about resource usage (memory, CPU)\n- container_action: User wants to start/stop/restart/update a container\n- container_status: User asks about container status\n- list_containers: User wants to see all containers\n- unknown: Cannot determine intent\n\nRespond with JSON: {\"action\": \"<action>\", \"container\": \"<name or null>\", \"parameters\": {}}\\n\\nExamples:\\n- \"show me plex logs\" -> {\"action\": \"view_logs\", \"container\": \"plex\", \"parameters\": {\"lines\": 50}}\\n- \"what's using the most memory?\" -> {\"action\": \"query_stats\", \"container\": null, \"parameters\": {\"metric\": \"memory\", \"sort\": \"desc\"}}\\n- \"restart nginx\" -> {\"action\": \"container_action\", \"container\": \"nginx\", \"parameters\": {\"action\": \"restart\"}}\\n- \"how's sonarr doing?\" -> {\"action\": \"container_status\", \"container\": \"sonarr\", \"parameters\": {}}\\n- \"hello\" -> {\"action\": \"unknown\", \"container\": null, \"parameters\": {\"message\": \"I can help with Docker containers. Try: 'show logs', 'restart plex', or 'what's using memory?'\"}}", "cache_control": {"type": "ephemeral"} } ], "messages": [ {"role": "user", "content": "{{$json.message}}"} ] }- Options: Timeout 30000ms, Retry on fail (3 attempts)
Note: n8n may need a "Header Auth" credential type created with the API key, OR use the body to include auth. Check n8n's HTTP Request node documentation for Anthropic compatibility.
Alternative if Header Auth credential doesn't work well:
- Use "None" authentication
- Add x-api-key header manually via "Send Headers" option
- Value: Use expression referencing an n8n credential or environment variable
- In n8n, navigate to Credentials and ensure Anthropic/Header credential is configured
- Test the HTTP Request node manually with a simple message like "hello"
- Check response contains valid JSON with action field Claude API HTTP Request node configured and able to receive intent parsing responses.
// Parse and validate Claude's intent response
const response = $input.item.json;
// Claude response structure: { content: [{ type: "text", text: "..." }] }
let intentText = '';
try {
intentText = response.content[0].text;
} catch (e) {
return {
action: 'error',
error: 'Invalid Claude response structure',
raw: JSON.stringify(response)
};
}
// Parse JSON from Claude's response
let intent;
try {
// Claude might wrap JSON in markdown code blocks, strip them
const cleaned = intentText.replace(/```json\n?/g, '').replace(/```\n?/g, '').trim();
intent = JSON.parse(cleaned);
} catch (e) {
return {
action: 'error',
error: 'Could not parse intent JSON',
raw: intentText
};
}
// Validate required fields
const validActions = ['view_logs', 'query_stats', 'container_action', 'container_status', 'list_containers', 'unknown'];
if (!intent.action || !validActions.includes(intent.action)) {
return {
action: 'unknown',
error: 'Invalid or missing action',
parameters: { message: 'I didn\'t understand that. Try: "show logs plex" or "restart nginx"' }
};
}
// Normalize container name if present
if (intent.container) {
intent.container = intent.container.toLowerCase().trim();
}
// Set defaults for parameters
intent.parameters = intent.parameters || {};
return intent;
-
After auth check (existing), route ALL messages through Claude Intent Parser first (not just unknown messages).
-
Add "Intent Router" Switch node after Parse Intent:
- Condition 1: action == "view_logs" -> Route to logs handler (from 04-01)
- Condition 2: action == "query_stats" -> Route to stats handler (placeholder for 04-03)
- Condition 3: action == "container_action" -> Route to existing actions branch
- Condition 4: action == "container_status" -> Route to existing status branch
- Condition 5: action == "list_containers" -> Route to existing status summary
- Condition 6: action == "unknown" -> Route to Unknown Intent handler
- Condition 7: action == "error" -> Route to Error handler
-
Create "Unknown Intent" handler:
- Telegram Send Message with helpful text from intent.parameters.message
- Default: "I can help manage your Docker containers. Try:\n- 'show logs plex'\n- 'restart sonarr'\n- 'what containers are running?'\n- 'what's using the most memory?'"
-
Create "Stats Placeholder" handler (will be replaced in 04-03):
- Returns: "Stats queries coming soon! For now, try 'status' to see running containers."
-
Update existing action/status handlers to use intent.container instead of re-parsing message.
Important: Keep existing command-based routing as fallback for when Claude API is unavailable (rate limit, error). Add error handling around Claude call that falls back to pattern matching. Test complete flow via Telegram:
- "show me nginx logs" -> routes to view_logs handler
- "restart plex" -> routes to container_action handler
- "how's sonarr?" -> routes to container_status handler
- "what's running" -> routes to list_containers handler
- "hello there" -> routes to unknown with helpful message
- "what's eating memory?" -> routes to stats placeholder All messages routed through Claude intent parsing with appropriate handler dispatch.
<success_criteria>
- Claude Sonnet 4.5 used for intent parsing with prompt caching
- Natural language queries parsed into structured intents
- All existing functionality (status, actions) accessible via conversation
- Graceful fallback/error handling when Claude unavailable
- Unknown intents guide users toward valid commands </success_criteria>