254 lines
10 KiB
Markdown
254 lines
10 KiB
Markdown
---
|
|
phase: 04-logs-intelligence
|
|
plan: 02
|
|
type: execute
|
|
wave: 1
|
|
depends_on: []
|
|
files_modified: [n8n-workflow.json]
|
|
autonomous: false
|
|
|
|
user_setup:
|
|
- service: anthropic
|
|
why: "Claude API for natural language understanding"
|
|
env_vars:
|
|
- name: ANTHROPIC_API_KEY
|
|
source: "Anthropic Console -> API Keys -> Create Key"
|
|
dashboard_config: []
|
|
|
|
must_haves:
|
|
truths:
|
|
- "Messages are parsed by Claude for intent detection"
|
|
- "Recognized intents route to appropriate handlers"
|
|
- "Unknown intents receive helpful response"
|
|
artifacts:
|
|
- path: "n8n-workflow.json"
|
|
provides: "Claude API integration and intent routing"
|
|
contains: "anthropic"
|
|
key_links:
|
|
- from: "Telegram message"
|
|
to: "Claude API"
|
|
via: "HTTP Request node"
|
|
pattern: "api.anthropic.com"
|
|
- from: "Claude response"
|
|
to: "Switch node"
|
|
via: "intent parsing code node"
|
|
pattern: "action.*view_logs|query_stats"
|
|
---
|
|
|
|
<objective>
|
|
Integrate Claude API for natural language understanding and intent-first message routing.
|
|
|
|
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.
|
|
</objective>
|
|
|
|
<execution_context>
|
|
@/home/luc/.claude/get-shit-done/workflows/execute-plan.md
|
|
@/home/luc/.claude/get-shit-done/templates/summary.md
|
|
</execution_context>
|
|
|
|
<context>
|
|
@.planning/PROJECT.md
|
|
@.planning/ROADMAP.md
|
|
@.planning/STATE.md
|
|
@.planning/phases/04-logs-intelligence/04-RESEARCH.md
|
|
@n8n-workflow.json
|
|
</context>
|
|
|
|
<tasks>
|
|
|
|
<task type="auto">
|
|
<name>Task 1: Add Claude API credential and HTTP Request node</name>
|
|
<files>n8n-workflow.json</files>
|
|
<action>
|
|
Create Claude API integration in the workflow.
|
|
|
|
1. 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):
|
|
```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
|
|
</action>
|
|
<verify>
|
|
1. In n8n, navigate to Credentials and ensure Anthropic/Header credential is configured
|
|
2. Test the HTTP Request node manually with a simple message like "hello"
|
|
3. Check response contains valid JSON with action field
|
|
</verify>
|
|
<done>Claude API HTTP Request node configured and able to receive intent parsing responses.</done>
|
|
</task>
|
|
|
|
<task type="auto">
|
|
<name>Task 2: Create intent parsing and validation logic</name>
|
|
<files>n8n-workflow.json</files>
|
|
<action>
|
|
After Claude HTTP Request node, add "Parse Intent" Code node to validate and extract the structured intent.
|
|
|
|
```javascript
|
|
// 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;
|
|
```
|
|
</action>
|
|
<verify>
|
|
Test Parse Intent node with various Claude responses:
|
|
1. Valid JSON response -> extracts action and container
|
|
2. Malformed JSON -> returns error action with helpful message
|
|
3. Missing action field -> returns unknown with guidance
|
|
</verify>
|
|
<done>Intent parsing extracts and validates Claude's response into usable workflow data.</done>
|
|
</task>
|
|
|
|
<task type="auto">
|
|
<name>Task 3: Wire intent router to existing and new handlers</name>
|
|
<files>n8n-workflow.json</files>
|
|
<action>
|
|
Restructure workflow to use intent-first routing:
|
|
|
|
1. After auth check (existing), route ALL messages through Claude Intent Parser first (not just unknown messages).
|
|
|
|
2. 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
|
|
|
|
3. 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?'"
|
|
|
|
4. Create "Stats Placeholder" handler (will be replaced in 04-03):
|
|
- Returns: "Stats queries coming soon! For now, try 'status' to see running containers."
|
|
|
|
5. 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.
|
|
</action>
|
|
<verify>
|
|
Test complete flow via Telegram:
|
|
1. "show me nginx logs" -> routes to view_logs handler
|
|
2. "restart plex" -> routes to container_action handler
|
|
3. "how's sonarr?" -> routes to container_status handler
|
|
4. "what's running" -> routes to list_containers handler
|
|
5. "hello there" -> routes to unknown with helpful message
|
|
6. "what's eating memory?" -> routes to stats placeholder
|
|
</verify>
|
|
<done>All messages routed through Claude intent parsing with appropriate handler dispatch.</done>
|
|
</task>
|
|
|
|
</tasks>
|
|
|
|
<checkpoint type="human-verify" gate="blocking">
|
|
<what-built>Claude API integration with intent-first message routing</what-built>
|
|
<how-to-verify>
|
|
1. Open Telegram chat with the bot
|
|
2. Send: "show me the logs for n8n"
|
|
- Expected: Should return n8n container logs (if 04-01 complete) or route correctly
|
|
3. Send: "restart plex" (or any container you can safely restart)
|
|
- Expected: Should trigger restart via existing action handler
|
|
4. Send: "hey how are you"
|
|
- Expected: Should return helpful message about available commands
|
|
5. Send: "what's using the most CPU?"
|
|
- Expected: Should return "Stats queries coming soon!" placeholder
|
|
6. Check n8n execution log to verify Claude API was called and intent parsed
|
|
</how-to-verify>
|
|
<resume-signal>Type "approved" if conversational routing works, or describe issues</resume-signal>
|
|
</checkpoint>
|
|
|
|
<verification>
|
|
After all tasks:
|
|
1. Claude API credential configured in n8n
|
|
2. HTTP Request node successfully calls Claude Messages API
|
|
3. Intent parsing extracts action, container, and parameters
|
|
4. Switch node routes to correct handlers based on intent
|
|
5. Unknown intents receive helpful guidance
|
|
6. Existing command-based functionality still works
|
|
</verification>
|
|
|
|
<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>
|
|
|
|
<output>
|
|
After completion, create `.planning/phases/04-logs-intelligence/04-02-SUMMARY.md`
|
|
</output>
|