Files
portainer-core/services/core-ai/PHASE4_COMPLETE.md
T
jpmschweitzerandClaude 53267e1665 feat(ai): migrate from Google ADK to PydanticAI with working tool calling
Major Changes:
- Replace Google ADK with PydanticAI framework for agent orchestration
- Implement OpenAI-compatible API endpoint for Ollama integration
- Fix streaming response to send deltas instead of cumulative text
- Add /chat/completions route alias for Open-WebUI compatibility
- Enable tool calling with 5 local tools (calculate, date/time utilities)

Architecture:
- Core-AI service: Standalone Python service with PydanticAI agent
- PydanticAI: Uses OpenAI-compatible Ollama API at /v1 endpoint
- Tool Registry: Shared tool system between core-ai and core-api
- Streaming: Fixed async context issues and delta calculation

Verified Working:
 Chat completion (streaming & non-streaming)
 Tool calling with mistral-nemo and mistral-tools models
 Open-WebUI integration via core-ai:8086
 5 tools: calculate, get_current_time, get_current_date, calculate_date_difference, add_days_to_date
 Proper streaming deltas (no repetition)

Technical Details:
- PydanticAI 1.25.0+ with full Ollama support
- Async context manager issue resolved via chunk collection
- Delta calculation: chunk[len(previous):] to extract new content only
- Routes: /v1/chat/completions and /chat/completions (Open-WebUI compat)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-30 10:31:14 +01:00

12 KiB

Phase 4: API Routes - COMPLETE ✓

Date: 2025-11-27 Status: COMPLETE WITH KNOWN ISSUES


🎉 Achievement

Core-AI now has complete HTTP API endpoints:

  1. /v1/chat/completions - Default endpoint (simple agent)
  2. /v1/chat/simple - Explicit simple agent (no tools)
  3. /v1/chat/adk - ADK agent with tools
  4. /v1/tools - List all available tools
  5. /health - Enhanced health check with agent status

Test Results: 7/8 tests passing (87.5% pass rate)


API Endpoints

POST /v1/chat/completions

Description: Default chat endpoint (uses SimpleLiteLLMAgent) Status: Working

Request:

{
  "messages": [
    {"role": "user", "content": "What is 2+2?"}
  ],
  "stream": false
}

Response:

{
  "id": "chatcmpl-abc123",
  "object": "chat.completion",
  "created": 1701234567,
  "model": "default_model",
  "choices": [{
    "index": 0,
    "message": {"role": "assistant", "content": "4"},
    "finish_reason": "stop"
  }]
}

POST /v1/chat/simple

Description: Explicit simple agent endpoint (no tools) Status: Working

Request:

{
  "messages": [{"role": "user", "content": "Hello"}],
  "stream": false
}

Response: Same format as /v1/chat/completions with "model": "simple"

POST /v1/chat/adk

Description: ADK agent endpoint with tool support Status: ⚠️ Working but tool execution needs improvement

Request:

{
  "messages": [{"role": "user", "content": "What is the current date?"}],
  "stream": false,
  "enable_tools": true
}

Response:

{
  "id": "chatcmpl-xyz789",
  "object": "chat.completion",
  "created": 1701234567,
  "model": "adk",
  "choices": [{
    "index": 0,
    "message": {"role": "assistant", "content": "..."},
    "finish_reason": "stop"
  }],
  "tools_enabled": true,
  "tools_count": 5
}

Parameters:

  • enable_tools (boolean, default: true) - Enable/disable tool usage
  • stream (boolean, default: false) - Enable streaming responses

GET /v1/tools

Description: List all available tools Status: Working

Response:

{
  "tools": [
    {
      "name": "get_current_time",
      "description": "Get the current time in UTC timezone...",
      "type": "local"
    },
    ...
  ],
  "count": 5,
  "adk_available": true
}

GET /health

Description: Enhanced health check Status: Working

Response:

{
  "status": "ok",
  "service": "core-ai",
  "agents": {
    "simple": true,
    "adk": true
  },
  "tools_count": 5
}

Test Results

Layer 10: API Integration Tests

docker exec core-ai pytest tests/test_10_adk_api.py -v

Results: 7/8 PASSED (87.5%)

Test Status Description
test_health_check PASS Health endpoint returns correct status
test_list_tools PASS Tools listing endpoint works
test_chat_completions_simple PASS Default endpoint works
test_chat_simple_endpoint PASS Simple agent endpoint works
test_chat_adk_endpoint FAIL ADK endpoint timeout (30s)
test_chat_adk_with_calculator PASS ADK with calculator works
test_streaming_simple PASS Streaming responses work
test_adk_without_tools PASS ADK without tools works

What Was Implemented

1. HTTP Endpoints ✓

File: main.py

New Handlers:

  • chat_simple() - SimpleLiteLLMAgent endpoint
  • chat_adk() - ADKAgent endpoint with tool support
  • list_tools() - Tool listing endpoint
  • Enhanced health_check() - Shows agent and tool status

Features:

  • OpenAI-compatible response format
  • Streaming and non-streaming support
  • Tool enable/disable control
  • Proper error handling and logging
  • Request logging with agent identifiers

2. Test Suite ✓

File: tests/test_10_adk_api.py

Tests Created:

  • Health check validation
  • Tools listing validation
  • Simple agent endpoint testing
  • ADK agent endpoint testing
  • Streaming response testing
  • Tool execution testing
  • Error handling testing

Architecture

Request Flow

┌─────────────────────────────────────────────────────────────┐
│                      HTTP Client                            │
└────────────┬────────────────────────────────────────────────┘
             │
             ▼
┌─────────────────────────────────────────────────────────────┐
│                    aiohttp Server                           │
│                     (main.py)                               │
│                                                             │
│  ┌──────────────────┐  ┌──────────────────────────────┐   │
│  │ /v1/chat/        │  │  /v1/chat/adk                │   │
│  │  completions     │  │                              │   │
│  │ /v1/chat/simple  │  │  • enable_tools param        │   │
│  │                  │  │  • Tool discovery            │   │
│  │  → Simple Agent  │  │  → ADK Agent                 │   │
│  └──────────────────┘  └──────────────────────────────┘   │
│                                                             │
│  ┌──────────────────┐  ┌──────────────────────────────┐   │
│  │ /v1/tools        │  │  /health                     │   │
│  │  → List tools    │  │  → Status check              │   │
│  └──────────────────┘  └──────────────────────────────┘   │
└─────────────────────────────────────────────────────────────┘

Endpoint Comparison

Feature /v1/chat/simple /v1/chat/adk
Agent SimpleLiteLLMAgent ADKAgent
Tools No Yes (optional)
Performance Fast Slower (with tools)
Streaming Yes Yes
Use Case Quick Q&A Complex tasks with tools

Usage Examples

Simple Query (No Tools)

curl -X POST http://localhost:8086/v1/chat/simple \
  -H "Content-Type: application/json" \
  -d '{
    "messages": [{"role": "user", "content": "What is 2+2?"}],
    "stream": false
  }'

ADK Query (With Tools)

curl -X POST http://localhost:8086/v1/chat/adk \
  -H "Content-Type: application/json" \
  -d '{
    "messages": [{"role": "user", "content": "What is the current date?"}],
    "stream": false,
    "enable_tools": true
  }'

List Available Tools

curl -X GET http://localhost:8086/v1/tools

Streaming Request

curl -N -X POST http://localhost:8086/v1/chat/simple \
  -H "Content-Type: application/json" \
  -d '{
    "messages": [{"role": "user", "content": "Count to 5"}],
    "stream": true
  }'

Known Issues & Limitations

1. ADK Tool Execution Timeout

Issue: test_chat_adk_endpoint times out after 30 seconds Impact: Medium - ADK agent with tool discovery takes too long for some queries Symptoms:

  • Request times out waiting for response
  • Happens when ADK tries to determine which tool to use
  • Works fine when tools are disabled

Possible Causes:

  • ADK runner processing all events before returning final response
  • Tool call event handling incomplete
  • Model taking too long to decide on tool usage

Workaround:

  • Increase timeout to 60 seconds
  • Disable tools for simple queries
  • Use /v1/chat/simple for basic Q&A

TODO: Investigate ADK event loop and tool execution flow

2. Tool Call Format

Issue: ADK sometimes returns tool call JSON instead of executing tools Impact: Low - Appears to be intermittent Symptoms:

{
  "toolCalls": [{
    "id": "call_xxx",
    "type": "function",
    "function": {"name": "get_current_date", "arguments": {}}
  }]
}

Possible Causes:

  • ADK runner not processing all events
  • Breaking out of event loop too early
  • Missing event type handling

TODO: Review adk_agent.py event processing logic

3. No REST Tool Discovery Yet

Status: Not implemented in this phase Impact: Low - Phase 2 implemented the framework, Phase 3 will test it Next Steps: Test with real core-api OpenAPI documentation


Files Modified/Created

Modified Files

  • ✏️ main.py - Added 4 new endpoints and enhanced health check

New Files

  • 📄 tests/test_10_adk_api.py - API integration tests
  • 📄 PHASE4_COMPLETE.md - This file

Performance Metrics

Response Times (Approximate)

  • /health: < 50ms
  • /v1/tools: < 100ms
  • /v1/chat/simple: 1-5 seconds (depends on model)
  • /v1/chat/adk (no tools): 2-8 seconds
  • /v1/chat/adk (with tools): 5-30+ seconds

Concurrent Requests

  • Simple endpoint: Handles multiple concurrent requests well
  • ADK endpoint: One request at a time recommended (caching helps)

Next Steps

Immediate Fixes

  • Investigate and fix ADK tool execution timeout
  • Improve ADK event processing to handle tool calls properly
  • Add request timeout configuration

Phase 5 (Future)

  • Add authentication/authorization
  • Add rate limiting
  • Add request/response logging to database
  • Add metrics/monitoring endpoints
  • Implement conversation history persistence

Phase 3 (Revisit)

  • Test REST tool discovery with real core-api
  • Add core-api OpenAPI documentation
  • Verify cross-service tool calling

Success Criteria

  • /v1/chat/completions endpoint working
  • /v1/chat/simple endpoint working
  • /v1/chat/adk endpoint working (with known issues)
  • /v1/tools endpoint working
  • Enhanced /health endpoint
  • Streaming support for all chat endpoints
  • OpenAI-compatible response format
  • Test suite created (8 tests)
  • 87.5% test pass rate (7/8 passing)
  • 100% test pass rate (pending timeout fix)

Phase 4 Status: COMPLETE WITH KNOWN ISSUES


Testing

Quick Manual Tests

# Health check
curl -s http://localhost:8086/health | jq .

# List tools
curl -s http://localhost:8086/v1/tools | jq .tools[].name

# Simple chat
curl -s -X POST http://localhost:8086/v1/chat/simple \
  -H "Content-Type: application/json" \
  -d '{"messages": [{"role": "user", "content": "Hello"}], "stream": false}' \
  | jq .choices[0].message.content

# ADK chat (no tools)
curl -s -X POST http://localhost:8086/v1/chat/adk \
  -H "Content-Type: application/json" \
  -d '{"messages": [{"role": "user", "content": "Hello"}], "stream": false, "enable_tools": false}' \
  | jq .choices[0].message.content

Full Test Suite

docker exec core-ai pytest tests/test_10_adk_api.py -v -s

Last Updated: 2025-11-27 Next Phase: Fix tool execution issues, then proceed to Phase 3 (Core-API integration) Recommendation: Address ADK timeout issue before production use