# Complete API Integration Guide - Codex ADK

**Status:** ✅ **PRODUCTION-READY** (All MVP Endpoints Implemented)
**Last Updated:** 2025-10-26
**Backend Version:** v1.0.0-mvp

---

## Overview

This guide covers the complete integration of all 13 backend API endpoints:
- **6 Commands** (write operations)
- **4 Queries** (read operations - CQRS pattern)
- **3 List Endpoints** (GET - simple reads, not yet implemented in frontend)

---

## Quick Reference

```dart
import 'package:console/api/api.dart';

final CqrsApiClient client = CqrsApiClient(
  config: ApiClientConfig.development, // http://localhost:5246
);

// Always dispose when done
client.dispose();
```

---

## 1. Agent Management

### Create Agent
```dart
final Result<void> result = await client.createAgent(
  CreateAgentCommand(
    name: 'Code Generator',
    description: 'AI code generation assistant',
    type: AgentType.codeGenerator,
    modelProvider: 'ollama',
    modelName: 'phi',
    providerType: ModelProviderType.localEndpoint,
    modelEndpoint: 'http://localhost:11434',
    systemPrompt: 'You are a code generation expert',
    temperature: 0.7,
    maxTokens: 4000,
    enableMemory: true,
    conversationWindowSize: 10,
  ),
);
```

### Get Agent
```dart
final Result<AgentDto> result = await client.getAgent('agent-uuid');

result.when(
  success: (AgentDto agent) {
    print('Name: ${agent.name}');
    print('Status: ${agent.status.value}');
    print('Model: ${agent.modelProvider}/${agent.modelName}');
  },
  error: (ApiErrorInfo error) => print('Error: ${error.message}'),
);
```

### Update Agent
```dart
await client.updateAgent(
  UpdateAgentCommand(
    id: 'agent-uuid',
    name: 'Updated Name',
    temperature: 0.8,
    status: AgentStatus.active,
  ),
);
```

### Delete Agent
```dart
await client.deleteAgent(
  DeleteAgentCommand(id: 'agent-uuid'),
);
```

**See:** `docs/AGENT_API_INTEGRATION.md` for complete Agent documentation.

---

## 2. Conversation Management

### Create Conversation
```dart
final Result<CreateConversationResult> result = await client.createConversation(
  CreateConversationCommand(
    title: 'Code Review Session',
    summary: 'Reviewing authentication module',
  ),
);

result.when(
  success: (CreateConversationResult created) {
    print('Conversation ID: ${created.id}');
  },
  error: (ApiErrorInfo error) => print('Error: ${error.message}'),
);
```

### Get Conversation
```dart
final Result<ConversationDto> result = await client.getConversation('conversation-uuid');

result.when(
  success: (ConversationDto conversation) {
    print('Title: ${conversation.title}');
    print('Messages: ${conversation.messageCount}');
    print('Started: ${conversation.startedAt}');
    print('Last message: ${conversation.lastMessageAt}');

    for (final ConversationMessageDto message in conversation.messages) {
      print('${message.role}: ${message.content}');
    }
  },
  error: (ApiErrorInfo error) => print('Error: ${error.message}'),
);
```

---

## 3. Agent Execution

### Start Agent Execution
```dart
final Result<StartExecutionResult> result = await client.startAgentExecution(
  StartAgentExecutionCommand(
    agentId: 'agent-uuid',
    conversationId: 'conversation-uuid', // Optional
    userPrompt: 'Generate a function to calculate factorial in Dart',
  ),
);

result.when(
  success: (StartExecutionResult started) {
    print('Execution started: ${started.id}');
  },
  error: (ApiErrorInfo error) => print('Error: ${error.message}'),
);
```

### Complete Agent Execution
```dart
await client.completeAgentExecution(
  CompleteAgentExecutionCommand(
    executionId: 'execution-uuid',
    status: ExecutionStatus.completed,
    response: 'Here is the factorial function: ...',
    inputTokens: 150,
    outputTokens: 300,
    estimatedCost: 0.0045,
  ),
);
```

### Get Agent Execution
```dart
final Result<AgentExecutionDto> result = await client.getAgentExecution('execution-uuid');

result.when(
  success: (AgentExecutionDto execution) {
    print('Status: ${execution.status.value}');
    print('Prompt: ${execution.userPrompt}');
    print('Response: ${execution.response}');
    print('Tokens: ${execution.inputTokens} in, ${execution.outputTokens} out');
    print('Cost: \$${execution.estimatedCost}');
    print('Duration: ${execution.completedAt?.difference(execution.startedAt)}');
  },
  error: (ApiErrorInfo error) => print('Error: ${error.message}'),
);
```

---

## 4. Health Check

```dart
final Result<bool> result = await client.checkHealth();

result.when(
  success: (bool isHealthy) => print('API healthy: $isHealthy'),
  error: (ApiErrorInfo error) => print('API unavailable: ${error.message}'),
);
```

---

## Complete Workflow Example

```dart
Future<void> completeAgentWorkflow() async {
  final CqrsApiClient client = CqrsApiClient(
    config: ApiClientConfig.development,
  );

  try {
    // 1. Create an agent
    print('1. Creating agent...');
    await client.createAgent(
      CreateAgentCommand(
        name: 'Code Generator',
        description: 'AI code generation assistant',
        type: AgentType.codeGenerator,
        modelProvider: 'ollama',
        modelName: 'phi',
        providerType: ModelProviderType.localEndpoint,
        modelEndpoint: 'http://localhost:11434',
        systemPrompt: 'You are a helpful code generation assistant',
        temperature: 0.7,
        maxTokens: 4000,
      ),
    );

    // Note: In real app, you'd get the agent ID from a list or create response
    final String agentId = 'your-agent-uuid';

    // 2. Create a conversation
    print('2. Creating conversation...');
    final Result<CreateConversationResult> convResult = await client.createConversation(
      CreateConversationCommand(
        title: 'Factorial Function Development',
      ),
    );

    String? conversationId;
    convResult.when(
      success: (CreateConversationResult created) {
        conversationId = created.id;
        print('   Conversation ID: $conversationId');
      },
      error: (ApiErrorInfo error) => print('   Failed: ${error.message}'),
    );

    // 3. Start agent execution
    print('3. Starting agent execution...');
    final Result<StartExecutionResult> execResult = await client.startAgentExecution(
      StartAgentExecutionCommand(
        agentId: agentId,
        conversationId: conversationId,
        userPrompt: 'Generate a Dart function to calculate factorial recursively',
      ),
    );

    String? executionId;
    execResult.when(
      success: (StartExecutionResult started) {
        executionId = started.id;
        print('   Execution ID: $executionId');
      },
      error: (ApiErrorInfo error) => print('   Failed: ${error.message}'),
    );

    // 4. Simulate agent processing (in real app, agent would process this)
    await Future<void>.delayed(Duration(seconds: 2));

    // 5. Complete the execution
    if (executionId != null) {
      print('4. Completing execution...');
      await client.completeAgentExecution(
        CompleteAgentExecutionCommand(
          executionId: executionId!,
          status: ExecutionStatus.completed,
          response: '''
int factorial(int n) {
  if (n <= 1) return 1;
  return n * factorial(n - 1);
}
          ''',
          inputTokens: 50,
          outputTokens: 100,
          estimatedCost: 0.0015,
        ),
      );
    }

    // 6. Get execution details
    if (executionId != null) {
      print('5. Fetching execution details...');
      final Result<AgentExecutionDto> detailsResult =
          await client.getAgentExecution(executionId!);

      detailsResult.when(
        success: (AgentExecutionDto execution) {
          print('   Status: ${execution.status.value}');
          print('   Response: ${execution.response}');
          print('   Tokens: ${execution.inputTokens} → ${execution.outputTokens}');
        },
        error: (ApiErrorInfo error) => print('   Failed: ${error.message}'),
      );
    }

    // 7. Get conversation with all messages
    if (conversationId != null) {
      print('6. Fetching conversation...');
      final Result<ConversationDto> convDetailsResult =
          await client.getConversation(conversationId!);

      convDetailsResult.when(
        success: (ConversationDto conv) {
          print('   Title: ${conv.title}');
          print('   Messages: ${conv.messageCount}');
          print('   Executions: ${conv.executionCount}');
        },
        error: (ApiErrorInfo error) => print('   Failed: ${error.message}'),
      );
    }

    print('\n✓ Workflow complete!');
  } finally {
    client.dispose();
  }
}
```

---

## Enums Reference

### AgentType
```dart
AgentType.codeGenerator  // 'CodeGenerator'
AgentType.codeReviewer   // 'CodeReviewer'
AgentType.debugger       // 'Debugger'
AgentType.documenter     // 'Documenter'
AgentType.custom         // 'Custom'
```

### AgentStatus
```dart
AgentStatus.active    // 'Active'
AgentStatus.inactive  // 'Inactive'
AgentStatus.error     // 'Error'
```

### ModelProviderType
```dart
ModelProviderType.cloudApi       // 'CloudApi' - OpenAI, Anthropic
ModelProviderType.localEndpoint  // 'LocalEndpoint' - Ollama
ModelProviderType.custom         // 'Custom'
```

### ExecutionStatus
```dart
ExecutionStatus.pending    // 'Pending'
ExecutionStatus.running    // 'Running'
ExecutionStatus.completed  // 'Completed'
ExecutionStatus.failed     // 'Failed'
ExecutionStatus.cancelled  // 'Cancelled'
```

---

## Error Handling Patterns

### Pattern 1: when() Method
```dart
result.when(
  success: (data) {
    // Handle success
  },
  error: (ApiErrorInfo error) {
    switch (error.type) {
      case ApiErrorType.network:
        showSnackbar('No internet connection');
      case ApiErrorType.timeout:
        showSnackbar('Request timed out - try again');
      case ApiErrorType.http:
        if (error.statusCode == 404) {
          showSnackbar('Resource not found');
        } else if (error.statusCode == 400) {
          showSnackbar('Invalid request: ${error.details}');
        }
      case ApiErrorType.validation:
        showValidationErrors(error.details);
      case ApiErrorType.serialization:
        logger.error('JSON parsing error: ${error.details}');
      case ApiErrorType.unknown:
        showSnackbar('Unexpected error occurred');
    }
  },
);
```

### Pattern 2: Switch Expression
```dart
final String message = switch (result) {
  ApiSuccess(value: final data) => 'Success: $data',
  ApiError(error: final err) when err.statusCode == 404 => 'Not found',
  ApiError(error: final err) when err.type == ApiErrorType.network => 'Network error',
  ApiError(error: final err) => 'Error: ${err.message}',
};
```

---

## Configuration

### Development
```dart
final CqrsApiClient client = CqrsApiClient(
  config: ApiClientConfig.development, // http://localhost:5246
);
```

### Android Emulator
```dart
final CqrsApiClient client = CqrsApiClient(
  config: ApiClientConfig(
    baseUrl: 'http://10.0.2.2:5246',
    timeout: Duration(seconds: 30),
  ),
);
```

### Production (with JWT)
```dart
final CqrsApiClient client = CqrsApiClient(
  config: ApiClientConfig(
    baseUrl: 'https://api.svrnty.com',
    timeout: Duration(seconds: 30),
    defaultHeaders: {
      'Content-Type': 'application/json',
      'Accept': 'application/json',
      'Authorization': 'Bearer $jwtToken',
    },
  ),
);
```

---

## Implementation Status

### ✅ Implemented (Phase 1 & 2)
- [x] Agent CRUD (create, get, update, delete)
- [x] Conversation creation and retrieval
- [x] Execution start, complete, and retrieval
- [x] Health check
- [x] All DTOs with strict typing
- [x] All enums
- [x] Functional error handling with Result<T>

### ⏳ Not Yet Implemented (Phase 3)
- [ ] List agents (GET /api/agents)
- [ ] List conversations (GET /api/conversations)
- [ ] List executions (GET /api/executions)
- [ ] Filter executions by status (GET /api/executions/status/{status})
- [ ] Agent-specific lists (GET /api/agents/{id}/conversations)

**Note:** Phase 3 endpoints use simple GET requests and return arrays. They can be added later based on UI requirements.

---

## Files Reference

### Implementation
- `lib/api/client.dart` - CQRS client core
- `lib/api/types.dart` - Result<T> and error types
- `lib/api/endpoints/agent_endpoint.dart` - Agent CRUD
- `lib/api/endpoints/conversation_endpoint.dart` - Conversation ops
- `lib/api/endpoints/execution_endpoint.dart` - Execution ops
- `lib/api/endpoints/health_endpoint.dart` - Health check
- `lib/api/api.dart` - Main export file

### Documentation
- `docs/AGENT_API_INTEGRATION.md` - Agent-specific guide
- `docs/COMPLETE_API_INTEGRATION.md` - This file
- `README_API.md` - CQRS architecture overview
- `CLAUDE.md` - Project conventions and rules

### Backend Contract
- `api-schema.json` - OpenAPI spec (source of truth)
- `../BACKEND/docs/openapi.json` - Backend source
- `../BACKEND/docs/COMPLETE-API-REFERENCE.md` - Backend API docs
- `../BACKEND/docs/CHANGELOG.md` - Breaking changes log

---

## Testing

### Run Analysis
```bash
flutter analyze
```

### Run Tests
```bash
flutter test
```

### Test Backend Connection
```bash
# Start backend first
cd ../BACKEND
dotnet run

# Then test from Flutter app
flutter run
```

---

## Important Notes

### CQRS Pattern
- All commands/queries use **POST** with JSON body
- Commands return `Result<void>` (except create operations that return IDs)
- Queries return `Result<T>` with typed data
- Always send JSON body, even empty `{}`

### Strict Typing
- No `dynamic` types allowed
- All variables have explicit type annotations
- All functions have typed parameters and return values
- See `CLAUDE.md` for complete typing rules

### Functional Error Handling
- Use `Result<T>` pattern matching
- Never use try-catch for API calls
- Use `when()` or switch expressions

### Backend Monitoring
```bash
# Always check backend changes before updating
cat ../BACKEND/docs/CHANGELOG.md

# Update API schema when backend changes
cp ../BACKEND/docs/openapi.json ./api-schema.json
```

---

## Next Steps

1. **Phase 3:** Implement list endpoints (GET operations)
2. **Authentication:** Add JWT token management (v2)
3. **Real-time:** WebSocket/SignalR for execution updates (v2)
4. **UI Components:** Build agent/conversation management screens
5. **State Management:** Integrate with Provider/Riverpod/Bloc

---

**Status:** ✅ **All Core Endpoints Implemented and Production-Ready**
**Last Updated:** 2025-10-26
**Backend Version:** v1.0.0-mvp
