> For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt.

# Reprocess AI Analysis SOP

Standard Operating Procedure for re-triggering AI analysis on calls that have already been processed or failed.

## Prerequisites

- AWS CLI configured with appropriate profile (e.g., `--profile rc`)
- Access to DynamoDB and S3 in the target region

## Environment Configuration

| Environment | Region    | Config Table                                       | Analysis Table                              | S3 Bucket                                |
| ----------- | --------- | -------------------------------------------------- | ------------------------------------------- | ---------------------------------------- |
| test        | us-west-2 | call-analytics-test-call-analysis-config-us-west-2 | call-analytics-test-call-analysis-us-west-2 | call-analytics-test-recordings-us-west-2 |
| prod        | us-east-1 | call-analytics-prod-call-analysis-config-us-east-1 | call-analytics-prod-call-analysis-us-east-1 | call-analytics-prod-recordings-us-east-1 |

## How AI Analysis Reprocessing Works

The `ai-analysis-processor` Lambda checks for existing analysis before processing:

1. Queries `call-analysis` table by `telephonySessionId`
2. If `s3AnalysisPath` exists and is non-empty → **SKIP** (already processed)
3. If `s3AnalysisPath` is missing or empty → **PROCESS** (continue with analysis)

To reprocess a call, you must:

1. Remove `s3AnalysisPath` from DynamoDB
2. Re-upload the transcript file to S3 (triggers EventBridge → SQS → Lambda)

## Step-by-Step Procedure

### Step 1: Verify Call Status

```bash
# Check current analysis status
aws dynamodb get-item \
  --profile rc \
  --region us-west-2 \
  --table-name call-analytics-test-call-analysis-us-west-2 \
  --key '{"telephonySessionId": {"S": "SESSION_ID_HERE"}}' \
  --projection-expression "s3AnalysisPath, s3TranscriptPath, aiAnalysisCompleted, aiAnalysisStarted, callResult, recordingAvailable" \
  --output json
```

**Check these fields:**

- `callResult` - If "Missed", call has no recording and cannot be analyzed
- `recordingAvailable` - Must be `true` for analysis to work
- `s3TranscriptPath` - Must exist to reprocess
- `s3AnalysisPath` - If present, analysis already exists

### Step 2: Remove s3AnalysisPath

```bash
aws dynamodb update-item \
  --profile rc \
  --region us-west-2 \
  --table-name call-analytics-test-call-analysis-us-west-2 \
  --key '{"telephonySessionId": {"S": "SESSION_ID_HERE"}}' \
  --update-expression "REMOVE s3AnalysisPath"
```

### Step 3: Re-upload Transcript to Trigger EventBridge

```bash
# Get the transcript path from DynamoDB output (s3TranscriptPath field)
# Example: orangeTheory/193365026/2025/12/09/transcripts/193365026-sa0d7c410eb431z19b0515b005z1852d680000/transcription.json

# Download transcript
aws s3 cp \
  "s3://call-analytics-test-recordings-us-west-2/TRANSCRIPT_PATH_HERE" \
  /tmp/transcription.json \
  --profile rc --region us-west-2

# Re-upload to trigger EventBridge
aws s3 cp \
  /tmp/transcription.json \
  "s3://call-analytics-test-recordings-us-west-2/TRANSCRIPT_PATH_HERE" \
  --profile rc --region us-west-2
```

### Step 4: Monitor Processing

EventBridge has a \~1 minute delay before the SQS message is delivered.

```bash
# Check Lambda logs
aws logs tail "/aws/lambda/call-analytics-test-ai-analysis-processor-ts-us-west-2" \
  --profile rc --region us-west-2 \
  --since 5m --format short | grep -E "SESSION_ID|SUCCESS|ERROR|complete"
```

### Step 5: Verify Completion

```bash
aws dynamodb get-item \
  --profile rc \
  --region us-west-2 \
  --table-name call-analytics-test-call-analysis-us-west-2 \
  --key '{"telephonySessionId": {"S": "SESSION_ID_HERE"}}' \
  --projection-expression "s3AnalysisPath, aiAnalysisCompleted" \
  --output json
```

Expected result:

```json
{
  "Item": {
    "s3AnalysisPath": { "S": "orangeTheory/.../ai-summary.json" },
    "aiAnalysisCompleted": { "BOOL": true }
  }
}
```

## Batch Reprocessing

For multiple calls, create a script:

```bash
#!/bin/bash
# reprocess-calls.sh

PROFILE="rc"
REGION="us-west-2"
TABLE="call-analytics-test-call-analysis-us-west-2"
BUCKET="call-analytics-test-recordings-us-west-2"

SESSION_IDS=(
  "s-a0d7c410eb431z19b0515b005z1852d680000"
  "s-another-session-id"
)

for SESSION_ID in "${SESSION_IDS[@]}"; do
  echo "Processing: $SESSION_ID"

  # Get transcript path
  TRANSCRIPT_PATH=$(aws dynamodb get-item \
    --profile $PROFILE --region $REGION \
    --table-name $TABLE \
    --key "{\"telephonySessionId\": {\"S\": \"$SESSION_ID\"}}" \
    --projection-expression "s3TranscriptPath" \
    --output json | jq -r '.Item.s3TranscriptPath.S')

  if [ "$TRANSCRIPT_PATH" == "null" ] || [ -z "$TRANSCRIPT_PATH" ]; then
    echo "  SKIP: No transcript path found"
    continue
  fi

  # Remove s3AnalysisPath
  aws dynamodb update-item \
    --profile $PROFILE --region $REGION \
    --table-name $TABLE \
    --key "{\"telephonySessionId\": {\"S\": \"$SESSION_ID\"}}" \
    --update-expression "REMOVE s3AnalysisPath"

  # Re-upload transcript
  aws s3 cp "s3://$BUCKET/$TRANSCRIPT_PATH" /tmp/transcript.json --profile $PROFILE --region $REGION
  aws s3 cp /tmp/transcript.json "s3://$BUCKET/$TRANSCRIPT_PATH" --profile $PROFILE --region $REGION

  echo "  DONE: Triggered reprocessing"
  sleep 2  # Avoid rate limiting
done
```

## Troubleshooting

### Error: "Missing required DynamoDB fields: inference\_config"

The client config is missing `inference_config`. Add it:

```bash
aws dynamodb update-item \
  --profile rc --region us-west-2 \
  --table-name call-analytics-test-call-analysis-config-us-west-2 \
  --key '{"client_id": {"S": "CLIENT_ID_HERE"}}' \
  --update-expression "SET inference_config = :ic" \
  --expression-attribute-values '{":ic": {"M": {"temperature": {"N": "1.0"}, "maxTokens": {"N": "16000"}}}}'
```

### Error: "Kimi JSON truncation / Unexpected end of JSON input"

`maxTokens` is too low for Kimi thinking model. Update to 16000:

```bash
aws dynamodb update-item \
  --profile rc --region us-west-2 \
  --table-name call-analytics-test-call-analysis-config-us-west-2 \
  --key '{"client_id": {"S": "CLIENT_ID_HERE"}}' \
  --update-expression "SET inference_config.maxTokens = :mt" \
  --expression-attribute-values '{":mt": {"N": "16000"}}'
```

### Error: "not authorized to perform: bedrock:InvokeModel"

IAM permissions missing for the region. Check `lib/stacks/iam-stack.ts` for Bedrock permissions.

### Call has callResult="Missed" or recordingAvailable=false

Missed calls have no recording and cannot be analyzed. This is expected behavior.

### SQS message stuck (ApproximateNumberOfMessagesNotVisible > 0)

Check visibility timeout (default: 960s / 16 minutes). Wait for timeout to expire or check DLQ for failed messages.

```bash
aws sqs get-queue-attributes \
  --profile rc --region us-west-2 \
  --queue-url "https://sqs.us-west-2.amazonaws.com/ACCOUNT_ID/call-analytics-test-ai-analysis-queue-us-west-2" \
  --attribute-names ApproximateNumberOfMessages ApproximateNumberOfMessagesNotVisible
```

## Related Documentation

- [Troubleshooting Guide](../05-DEVELOPMENT/guides/troubleshooting.md)
- [Lambda Architecture](../05-DEVELOPMENT/reference/lambda-architecture.md)
- [Monitoring Guide](01-MONITORING/README.md)
