﻿# Lysande LLM Integration

Primary agent entrypoint: `https://lysande.ai/skill.md`

This document explains how an AI agent can connect to Lysande using human-approved claim activation.

## Goal
Allow an AI agent to act on behalf of a user in Lysande after explicit user approval.

## Connect Flow (human-in-the-loop claim)
1. Agent calls `POST /functions/v1/os-lys-agent-join`.
2. Agent receives `claim_url` + agent `api_key`.
3. Agent asks human to open `claim_url`.
4. Human logs in on `/connect`.
5. `/connect` activates claim automatically via `POST /functions/v1/os-lys-agent-activate`.
6. Agent polls `GET /functions/v1/os-lys-agent-claim-status` until active.
7. Agent uses:
   - `Authorization: Bearer <AGENT_KEY>`
   - `apikey: <SUPABASE_PUBLISHABLE_KEY>`

## Agent routes (current)
Base URL:
- `https://rukqpqmurijczzzkzlce.supabase.co/functions/v1`

Routes:
- `POST /os-lys-agent-join`
- `POST /os-lys-agent-activate`
- `GET /os-lys-agent-claim-status`
- `GET /os-lys-agent-me`
- `GET /os-lys-agent-projects`
- `GET /os-lys-agent-project-scores`
- `GET /os-lys-agent-project-prompts`
- `GET /os-lys-agent-project-personas`
- `GET /os-lys-agent-project-prompt-runs`
- `GET /os-lys-agent-prompt-run-details`
- `GET /os-lys-agent-project-overview`
- `GET /os-lys-agent-project-recommendations`
- `POST /os-lys-agent-onboarding-start`
- `GET /os-lys-agent-onboarding-run-status`
- `GET /os-lys-agent-onboarding-runs`

## Skill: Get user projects
After claim is activated, list all projects the user can access (owned + collaborations):

```http
GET https://rukqpqmurijczzzkzlce.supabase.co/functions/v1/os-lys-agent-projects
Authorization: Bearer <AGENT_KEY>
apikey: <SUPABASE_PUBLISHABLE_KEY>
```

## Skill: Get project scores
Ask your agent:
- "What score does project <name/id> have?"

Agent calls:

```http
GET https://rukqpqmurijczzzkzlce.supabase.co/functions/v1/os-lys-agent-project-scores
Authorization: Bearer <AGENT_KEY>
apikey: <SUPABASE_PUBLISHABLE_KEY>
```

For a single project:

```http
GET https://rukqpqmurijczzzkzlce.supabase.co/functions/v1/os-lys-agent-project-scores?project_id=<PROJECT_ID>
Authorization: Bearer <AGENT_KEY>
apikey: <SUPABASE_PUBLISHABLE_KEY>
```

Expected response shape:
- `ok: boolean`
- `count: number`
- `results: [{ project, score }]`
- `score` includes: `overall_score`, `geo_score`, `prompt_coverage`, `citation_rate`

If not activated yet:
- `403` with `{"error":"Agent connection is not activated"}`

## Skill: Get project prompts
Ask your agent:
- "Show prompts for project <name/id>"
- "List all prompts connected to my projects"

Agent calls:

```http
GET https://rukqpqmurijczzzkzlce.supabase.co/functions/v1/os-lys-agent-project-prompts
Authorization: Bearer <AGENT_KEY>
apikey: <SUPABASE_PUBLISHABLE_KEY>
```

For a single project:

```http
GET https://rukqpqmurijczzzkzlce.supabase.co/functions/v1/os-lys-agent-project-prompts?project_id=<PROJECT_ID>
Authorization: Bearer <AGENT_KEY>
apikey: <SUPABASE_PUBLISHABLE_KEY>
```

Optional filters:
- `limit=<1-1000>` (default `200`)
- `q=<text>` (substring filter in prompt text)
- `source_type=<value>` (example: `persona`)

Expected response shape:
- `ok: boolean`
- `count: number`
- `results: [{ project, prompt }]`
- `project`: `id`, `name`, `relation`
- `prompt`: `id`, `text`, `category`, `locale`, `region`, `source_type`, `source_persona_id`, `source_persona_name`, `source_signals`

## Skill: Get project personas and maps
Ask your agent:
- "Show personas for project <name/id>"
- "Show persona maps (folders) in this project"

Agent calls:

```http
GET https://rukqpqmurijczzzkzlce.supabase.co/functions/v1/os-lys-agent-project-personas
Authorization: Bearer <AGENT_KEY>
apikey: <SUPABASE_PUBLISHABLE_KEY>
```

Filter on one project:

```http
GET https://rukqpqmurijczzzkzlce.supabase.co/functions/v1/os-lys-agent-project-personas?project_id=<PROJECT_ID>
Authorization: Bearer <AGENT_KEY>
apikey: <SUPABASE_PUBLISHABLE_KEY>
```

Optional filters:
- `folder_id=<FOLDER_ID>` (personas in one map)
- `q=<text>` (search in persona name/summary/role)
- `limit=<1-1000>` (default `200`, personas list)

Expected response shape:
- `ok: boolean`
- `count: { maps: number, personas: number }`
- `results.maps: [{ project, map }]`
- `results.personas: [{ project, persona }]`

## Skill: Get prompt run details (test prompt runs)
Ask your agent:
- "Show test runs for prompt `<prompt_id>`"
- "Which sources were cited for this prompt?"
- "How many runs and mentions does this prompt have?"

Agent calls:

```http
GET https://rukqpqmurijczzzkzlce.supabase.co/functions/v1/os-lys-agent-project-prompt-runs?prompt_id=<PROMPT_ID>
Authorization: Bearer <AGENT_KEY>
apikey: <SUPABASE_PUBLISHABLE_KEY>
```

Optional filters:
- `project_id=<PROJECT_ID>` (extra scope check)
- `include_answers=true|false` (default `true`)
- `limit=<1-5000>` (default `2000`, number of prompt run result rows to inspect)

Expected response shape:
- `ok: boolean`
- `project`: `id`, `name`, `relation`
- `prompt`: prompt metadata (`id`, `text`, `category`, `locale`, `source_*`)
- `summary`: `run_count`, `response_count`, `mention_count`, `mention_rate`, `citation_count`, `last_run_at`
- `citations.domains`: top cited domains with counts
- `citations.top_urls`: top cited URLs with counts
- `test_runs`: grouped run history (similar to `/test-prompts/[id]`) with:
  - run-level stats (`ok_tests`, `error_tests`, `mention_rate`, `citation_count`)
  - provider responses and citations per response

## Skill: Get deep test prompt analytics (run details + provider stats)
Ask your agent:
- "Show deep run analytics for prompt `<prompt_id>`"
- "What was cited, by provider, in the latest runs?"
- "Show mention/sentiment/tokens per provider for this prompt"

Agent calls:

```http
GET https://rukqpqmurijczzzkzlce.supabase.co/functions/v1/os-lys-agent-prompt-run-details?prompt_id=<PROMPT_ID>
Authorization: Bearer <AGENT_KEY>
apikey: <SUPABASE_PUBLISHABLE_KEY>
```

Optional filters:
- `project_id=<PROJECT_ID>` (extra scope check)
- `provider=<openai|gemini|perplexity>`
- `run_id=<RUN_ID>`
- `batch_id=<BATCH_ID>`
- `include_answers=true|false` (default `true`)
- `include_raw_response=true|false` (default `false`)
- `limit=<1-5000>` (default `3000`, response rows)
- `run_limit=<1-500>` (default `100`, grouped runs in output)

Expected response shape:
- `project`, `prompt`
- `summary`: run/response totals, mention/citation rates, token totals, avg latency
- `provider_stats`: per-provider performance (ok/error, mentions, sentiment breakdown, citations, tokens)
- `citations.domains` and `citations.top_urls`
- `test_runs`: grouped run history with per-response details (`mention_reason`, `sentiment`, `latency_ms`, tokens, citations, optional answer/raw_response)

## Skill: Get project overview snapshot
Ask your agent:
- "Give me the latest overview for project `<project_id>`"
- "Show trend deltas and diagnostics for my projects"

Agent calls:

```http
GET https://rukqpqmurijczzzkzlce.supabase.co/functions/v1/os-lys-agent-project-overview
Authorization: Bearer <AGENT_KEY>
apikey: <SUPABASE_PUBLISHABLE_KEY>
```

Optional filters:
- `project_id=<PROJECT_ID>`
- `include_history=true|false` (default `true`)
- `history_limit=<1-10>` (default `2`)
- `project_limit=<1-200>` (default `50`)

Expected response shape:
- `results: [{ project, overview, summary, latest_snapshot, history }]`
- `summary` includes latest `overall_score`, `geo_score`, `prompt_coverage`, `citation_rate`, plus delta trend when previous snapshot exists.

## Skill: Get project recommendations
Ask your agent:
- "Show recommendations for project `<project_id>`"
- "List high priority recommendations across my projects"

Agent calls:

```http
GET https://rukqpqmurijczzzkzlce.supabase.co/functions/v1/os-lys-agent-project-recommendations
Authorization: Bearer <AGENT_KEY>
apikey: <SUPABASE_PUBLISHABLE_KEY>
```

Optional filters:
- `project_id=<PROJECT_ID>`
- `type=<TYPE>`
- `priority=<PRIORITY>`
- `q=<text>`
- `limit=<1-2000>` (default `200`)

Expected response shape:
- `results: [{ project, recommendation }]`
- `stats.by_type`, `stats.by_priority`, `stats.by_project`

## Skill: Start onboarding for a project
Ask your agent:
- "Start onboarding for project `<project_id>`"
- "Run onboarding in English for this project"
- "Start onboarding for `https://example.com`"

Agent calls:

```http
POST https://rukqpqmurijczzzkzlce.supabase.co/functions/v1/os-lys-agent-onboarding-start
Authorization: Bearer <AGENT_KEY>
apikey: <SUPABASE_PUBLISHABLE_KEY>
Content-Type: application/json

{
  "project_id": "<PROJECT_ID>",
  "language": "en",
  "verbose": true,
  "steps": {
    "brand": true,
    "intent": true,
    "prompts": true,
    "tests": true,
    "competitors": false,
    "technical": true
  },
  "limits": {
    "promptLimit": 10,
    "competitorLimit": 12
  }
}
```

Request body:
- `project_id` (optional)
- `url` (optional)
- `language`, `country` (optional)
- `verbose` (optional, default `true`)
- `steps` (optional)
- `limits.promptLimit`, `limits.competitorLimit` (optional)
- `performCompetitorAnalysis`, `performTechnicalAeo` (optional)

Resolution rules:
- If `project_id` is provided, that project is used.
- If `project_id` is missing, `url` is required.
- If `url` matches an existing accessible project domain, that project is reused.
- If no match is found, onboarding is still started via engine URL-flow (frontend-like behavior), which may create/select a project upstream.

Expected response shape:
- `ok: boolean`
- `project: { id, name, relation }`
- `run: { id, channel, status }`
- `upstream`: raw onboarding start payload from engine

## Skill: Check onboarding run status
Ask your agent:
- "Is onboarding run `<run_id>` complete?"
- "Show step status and warnings for this onboarding run"

Agent calls:

```http
GET https://rukqpqmurijczzzkzlce.supabase.co/functions/v1/os-lys-agent-onboarding-run-status?run_id=<RUN_ID>
Authorization: Bearer <AGENT_KEY>
apikey: <SUPABASE_PUBLISHABLE_KEY>
```

Optional filters:
- `include_steps=true|false` (default `true`)

Expected response shape:
- `ok: boolean`
- `project: { id, name, relation }`
- `run`: onboarding run fields (`status`, `current_step`, `progress`, `updated_at`, errors/warnings)
- `resume`: `{ canResume, status }`
- `summary.by_status`: step status counts
- `steps`: normalized onboarding step rows (`step_key`, `status`, `detail`, `error_message`, `warning_message`)

## Skill: List onboarding runs
Ask your agent:
- "Show recent onboarding runs for project `<project_id>`"
- "List all running/failed onboarding runs"

Agent calls:

```http
GET https://rukqpqmurijczzzkzlce.supabase.co/functions/v1/os-lys-agent-onboarding-runs
Authorization: Bearer <AGENT_KEY>
apikey: <SUPABASE_PUBLISHABLE_KEY>
```

Optional filters:
- `project_id=<PROJECT_ID>`
- `status=<started|running|succeeded|failed|...>`
- `limit=<1-200>` (default `50`)

Expected response shape:
- `ok: boolean`
- `count: number`
- `results: [{ project, run, steps_summary }]`

## Recommended agent behavior
- Always ask for user approval before requesting login.
- Request the minimal permissions needed.
- Never ask for passwords.
- Never log or expose API keys in plain text after connection.
- Rotate/revoke keys if compromised.

## Notes
- Claim activation flow is live.
- Human consent is required for every connection.
