# Internal Agentic AI Example - Medical Research Assistant

Demonstrates agentic AI-specific SDK features with complete Registry API integration for multi-step autonomous agents.

## What is Agentic AI?

Agentic AI systems are autonomous agents that:
- Define and pursue goals
- Use multiple tools to gather information
- Perform multi-step reasoning
- Make decisions with optional human oversight

## Features Demonstrated

- ✅ GCP Authentication (Application Default Credentials)
- ✅ OTel Collector connectivity verification
- ✅ Registry API integration (filtering by model type + config fetch)
- ✅ Goal tracking with `record_goal_started/completed()`
- ✅ Tool execution tracking with `track_tool()`
- ✅ Multi-step reasoning spans with `reasoning_step()`
- ✅ Human intervention recording
- ✅ Policy violation tracking (`record_policy_violation()`)
- ✅ Error tracking with goal context
- ✅ Telemetry verification in GCP services

## Architecture

```
┌─────────────────────────────────────────────────────────┐
│          Medical Research Assistant Agent               │
│                                                          │
│  Goal: "What are latest T2D treatments with CVD?"       │
│                                                          │
│  ┌────────────┐   ┌────────────┐   ┌────────────┐      │
│  │  Planning  │ → │  Research  │ → │  Analysis  │      │
│  └────────────┘   └────────────┘   └────────────┘      │
│                                                          │
│  ┌────────────┐   ┌────────────┐   ┌────────────┐      │
│  │    Query   │ → │ Synthesize │ → │   Human    │      │
│  │  Drug DB   │   │   Answer   │   │  Intervention│    │
│  └────────────┘   └────────────┘   └────────────┘      │
└─────────────────────────────────────────────────────────┘
           │                    │                  │
           ▼                    ▼                  ▼
     PubMed Search        Drug Database       Calculator
     (Mock Tool)          (Mock Tool)         (Mock Tool)
```

## Prerequisites

### 1. Install Dependencies

```bash
pip install mca-sdk[gcp,genai]>=0.6.1
```

### 2. Configure GCP Authentication

```bash
gcloud auth application-default login
```

### 3. VPN Connection (if outside GKE cluster)

The GCP dev OTel Collector (`10.164.76.55`) is only accessible from inside the GKE cluster or via VPN.

## Usage

### Run Against GCP Dev Collector (Default)

```bash
python agent_instrumented.py
```

**Note:** Requires VPN access if running outside the GKE cluster.

### Run Against Local Collector (Optional)

```bash
docker-compose up -d otel-collector
export MCA_COLLECTOR_ENDPOINT=http://localhost:4318
python agent_instrumented.py
```

## Using GCP Development Infrastructure

To test against the real GCP dev environment instead of a local collector:

```bash
# Use Docker Compose override
docker-compose -f ../../docker-compose.yml -f ../../docker-compose.gcp-dev.yml up internal-agentic

# Or set environment variables for local testing
export MCA_COLLECTOR_ENDPOINT=http://10.164.76.55:4318
export MCA_ALLOW_INSECURE_COLLECTOR=true
python agent_instrumented.py
```

See [GCP Dev Environment Guide](../../../docs/gcp-dev-environment.md) for complete setup instructions and troubleshooting.

### Verification

After running against GCP dev, verify telemetry in GCP Console:

```bash
# View logs
gcloud logging read "logName=projects/bhsf-ai-team-projects/logs/emms-model-telemetry" --limit=10

# View traces
gcloud trace list --project=bhsf-ai-team-projects --limit=10
```

Or use the GCP Console:
- **Logs**: [https://console.cloud.google.com/logs/query?project=bhsf-ai-team-projects](https://console.cloud.google.com/logs/query?project=bhsf-ai-team-projects)
- **Traces**: [https://console.cloud.google.com/traces/list?project=bhsf-ai-team-projects](https://console.cloud.google.com/traces/list?project=bhsf-ai-team-projects)

### Troubleshooting GCP Connectivity

**Cannot connect to 10.164.76.55:**
- Verify VPC connectivity or VPN access
- Test with: `curl http://10.164.76.55:4318/`

**Telemetry not appearing in GCP Console:**
- Verify collector endpoint is set correctly
- Check collector health: `curl http://10.164.76.55:13133/health/status`
- Wait 15 seconds for batch processing

## Expected Output

The script will:
1. Verify GCP authentication and collector connectivity
2. Filter registry for agentic models (demonstrates discovery)
3. Fetch specific model configuration
4. Initialize SDK with agentic model type
5. Start goal tracking for research question
6. Execute planning step with reasoning span
7. Call tools (PubMed search, drug database) with tracking
8. Perform multi-step reasoning (evaluation, synthesis)
9. Record human intervention request
10. Complete goal with success metrics
11. Test policy violation detection
12. Flush telemetry to collector
13. Print verification URLs for GCP Console

## Mock Mode

All tools are mocked with predefined responses:
- **PubMed Search**: Returns hardcoded research paper summaries
- **Drug Database**: Returns predefined drug information
- **Calculator**: Performs safe arithmetic

**No external API calls are made**, making this suitable for demo purposes without requiring real API keys or database access.

## Customization

### Add New Tools
Edit `tools.py` to add more mock tools:
```python
class MockNewTool:
    def execute(self, params):
        # Your implementation
        pass
```

### Modify Research Question
Edit the `question` variable in `agent_instrumented.py`:
```python
question = "Your custom clinical research question"
```

### Adjust Instrumentation
The agent uses standard OpenTelemetry APIs:
- `tracer.start_as_current_span()` for traces
- `counter.add()` for metrics
- `histogram.record()` for latency

## HIPAA Compliance & Sensitive Data Protection

**CRITICAL:** This example demonstrates telemetry in a healthcare context.

### Sensitive Data Handling Requirements

1. **Never include Sensitive Data in telemetry data**
   - Patient names, MRNs, dates of birth, SSNs
   - Specific addresses, phone numbers, email addresses
   - Protected health information per HIPAA

2. **Sanitize inputs before instrumentation**
   ```python
   # BAD - May expose Sensitive Data
   goal_id = client.record_goal_started(
       goal_description=user_question  # Might contain Sensitive Data!
   )

   # GOOD - Sanitized
   sanitized_question = remove_sensitive_data(user_question[:100])
   goal_id = client.record_goal_started(
       goal_description=sanitized_question
   )
   ```

3. **Review all span attributes**
   - `goal_description` - Truncate and sanitize
   - `tool.input_tokens` - Safe (numeric)
   - `tool.output_tokens` - Safe (numeric)
   - Custom attributes - Review for Sensitive Data

4. **Error messages**
   - SDK automatically sanitizes error messages
   - But review custom error handling code

### This Example's Sensitive Data Protection

- Questions are truncated to 100 characters maximum
- Mock data contains no real Sensitive Data
- Error messages sanitized for CREDENTIALS only (not Sensitive Data) via `_sanitize_error_message()`
- OTel logs use structured logging (no free-form text)

**For production:** Implement organization-specific Sensitive Data detection and removal before any telemetry recording.

## Production Considerations

For production deployment:
1. **Implement Sensitive Data sanitization** - Use NER models or regex patterns to detect/remove Sensitive Data
2. Replace mock tools with real API clients (PubMed API, drug databases)
3. Add authentication and rate limiting for external APIs
4. Implement caching to reduce API calls
5. Add retry logic with exponential backoff
6. Use LangChain's agent framework for more sosensitive_datasticated reasoning
7. Implement proper error handling and fallback strategies
8. Add data validation for tool inputs/outputs
9. Consider using LangSmith or similar for agent debugging

## Integration with LangChain

While this example uses simple Python classes, production agentic systems often use frameworks like LangChain:

```python
from langchain.agents import AgentExecutor, create_react_agent
from langchain.tools import Tool

# Define tools as LangChain Tools
tools = [
    Tool(
        name="PubMed Search",
        func=pubmed.search,
        description="Search PubMed for medical research papers"
    )
]

# Create agent (with MCA SDK instrumentation)
agent = create_react_agent(llm, tools, prompt)
executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
```

Add MCA SDK instrumentation at key points in the LangChain callbacks.

## License

See main project LICENSE.
