{"id":21081804,"url":"https://github.com/openvoiceos/ovos-persona-server","last_synced_at":"2026-06-12T19:00:45.809Z","repository":{"id":196397358,"uuid":"696005022","full_name":"OpenVoiceOS/ovos-persona-server","owner":"OpenVoiceOS","description":null,"archived":false,"fork":false,"pushed_at":"2026-06-10T04:57:17.000Z","size":205,"stargazers_count":3,"open_issues_count":13,"forks_count":1,"subscribers_count":4,"default_branch":"dev","last_synced_at":"2026-06-10T06:30:52.738Z","etag":null,"topics":["openvoiceos"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/OpenVoiceOS.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["OpenVoiceOS"],"patreon":"openvoiceos","liberapay":"OpenVoiceOS-Foundation","custom":"https://paypal.me/openvoiceos"}},"created_at":"2023-09-24T21:19:18.000Z","updated_at":"2026-03-08T18:31:44.000Z","dependencies_parsed_at":"2025-04-30T20:28:18.961Z","dependency_job_id":"633440ee-605f-40f4-bd49-495588fa9b0f","html_url":"https://github.com/OpenVoiceOS/ovos-persona-server","commit_stats":null,"previous_names":["openvoiceos/ovos-persona-server"],"tags_count":17,"template":false,"template_full_name":null,"purl":"pkg:github/OpenVoiceOS/ovos-persona-server","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenVoiceOS%2Fovos-persona-server","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenVoiceOS%2Fovos-persona-server/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenVoiceOS%2Fovos-persona-server/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenVoiceOS%2Fovos-persona-server/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/OpenVoiceOS","download_url":"https://codeload.github.com/OpenVoiceOS/ovos-persona-server/tar.gz/refs/heads/dev","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenVoiceOS%2Fovos-persona-server/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34258372,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-12T02:00:06.859Z","response_time":109,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["openvoiceos"],"created_at":"2024-11-19T20:11:02.655Z","updated_at":"2026-06-12T19:00:45.794Z","avatar_url":"https://github.com/OpenVoiceOS.png","language":"Python","funding_links":["https://github.com/sponsors/OpenVoiceOS","https://patreon.com/openvoiceos","https://liberapay.com/OpenVoiceOS-Foundation","https://paypal.me/openvoiceos"],"categories":[],"sub_categories":[],"readme":"# ovos-persona-server\n\nA single HTTP server that exposes one OVOS `Persona` as **eight concurrent API surfaces** — so any LLM client (OpenAI SDK, LangChain, Ollama tools, Anthropic SDK, Google Gemini SDK, Cohere SDK, HuggingFace TGI client, AWS Bedrock client, or any A2A agent) can talk to your OVOS persona without changes.\n\n---\n\n## Table of Contents\n\n- [What is a Persona?](#what-is-a-persona)\n- [Installation](#installation)\n- [Quick Start](#quick-start)\n- [API Surfaces](#api-surfaces)\n- [A2A Endpoint](#a2a-endpoint)\n- [Persona Config Examples](#persona-config-examples)\n- [Streaming](#streaming)\n- [Embeddings](#embeddings)\n- [Authentication](#authentication)\n- [Troubleshooting](#troubleshooting)\n\n---\n\n## What is a Persona?\n\nAn OVOS Persona is a JSON file that chains together one or more **solver plugins**. Solvers are tried in order until one returns an answer. You can mix LLMs, knowledge bases, and fallback bots in a single persona — no GPU required for non-LLM setups.\n\n```json\n{\n  \"name\": \"OldSchoolBot\",\n  \"solvers\": [\n    \"ovos-solver-wikipedia-plugin\",\n    \"ovos-solver-ddg-plugin\",\n    \"ovos-solver-plugin-wolfram-alpha\",\n    \"ovos-solver-wordnet-plugin\",\n    \"ovos-solver-rivescript-plugin\",\n    \"ovos-solver-failure-plugin\"\n  ],\n  \"ovos-solver-plugin-wolfram-alpha\": { \"appid\": \"YOUR_API_KEY\" }\n}\n```\n\nFind solver plugins at [github.com/OpenVoiceOS](https://github.com/OpenVoiceOS?q=solver).\n\n---\n\n## Installation\n\n```bash\n# Base server (no A2A)\npip install ovos-persona-server\n\n# With A2A server support\npip install 'ovos-persona-server[a2a]'\n```\n\nWith `uv` (recommended in OVOS workspaces):\n\n```bash\nuv pip install 'ovos-persona-server[a2a]'\n```\n\n---\n\n## Quick Start\n\n```bash\n# Start serving a persona on port 8337\novos-persona-server --persona /path/to/my-persona.json\n\n# Also expose it as an A2A agent\novos-persona-server \\\n  --persona /path/to/my-persona.json \\\n  --a2a-base-url http://localhost:8337/a2a\n```\n\nThe server binds to `0.0.0.0:8337` by default. Visit `http://localhost:8337/docs` for the interactive API reference (Swagger UI).\n\n---\n\n## API Surfaces\n\nEvery API is served on a vendor-prefixed path so multiple clients can coexist without conflict.\n\n| API | Prefix | Key endpoints |\n|-----|--------|---------------|\n| OpenAI | `/openai/v1` | `POST /chat/completions`, `POST /completions`, `GET /models`, `POST /embeddings` |\n| Ollama | `/ollama/api` | `POST /chat`, `POST /generate`, `GET /tags`, `POST /embeddings` |\n| Anthropic | `/anthropic/v1` | `POST /messages` |\n| Google Gemini | `/gemini/v1beta/models` | `POST /{model}:generateContent`, `POST /{model}:streamGenerateContent` |\n| Cohere | `/cohere/v1` | `POST /chat` |\n| HuggingFace TGI | `/tgi` | `POST /generate`, `POST /generate_stream` |\n| AWS Bedrock | `/bedrock/model` | `POST /{model}/invoke`, `POST /{model}/invoke-with-response-stream` |\n| A2A | `/a2a` | `GET /.well-known/agent.json`, `POST /` |\n\n### Deprecated legacy paths\n\nFor backwards compatibility, `/v1/...` maps to `/openai/v1/...` and `/api/...` maps to `/ollama/api/...`. These paths send `Deprecation` and `Link` response headers and will be removed in a future major version. Migrate to the prefixed paths.\n\n### Quick test with curl\n\n```bash\n# OpenAI-compatible chat\ncurl -s http://localhost:8337/openai/v1/chat/completions \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"model\":\"\",\"messages\":[{\"role\":\"user\",\"content\":\"hello\"}]}' \\\n  | python3 -m json.tool\n\n# Ollama-compatible chat\ncurl -s http://localhost:8337/ollama/api/chat \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"model\":\"\",\"messages\":[{\"role\":\"user\",\"content\":\"hello\"}]}'\n```\n\n---\n\n## A2A Endpoint\n\n`ovos-persona-server` can expose your persona as a standard [A2A](https://google.github.io/A2A/) agent server, enabling any A2A client to interact with it — including **ovos-a2a-agent** running on another OVOS instance.\n\n### Enable A2A\n\n```bash\novos-persona-server \\\n  --persona my-persona.json \\\n  --a2a-base-url http://myhost:8337/a2a\n```\n\nThe `--a2a-base-url` flag:\n- Activates the A2A endpoint at `/a2a`.\n- Sets the `url` field in the Agent Card returned at `GET /a2a/.well-known/agent.json`.\n- Must be the **publicly reachable** URL of the `/a2a` mount — this is what A2A clients use to discover the server.\n\n### Verify\n\n```bash\n# Fetch the Agent Card\ncurl http://localhost:8337/a2a/.well-known/agent.json | python3 -m json.tool\n\n# Send a message\ncurl -X POST http://localhost:8337/a2a/ \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"jsonrpc\": \"2.0\",\n    \"id\": \"1\",\n    \"method\": \"message/send\",\n    \"params\": {\n      \"message\": {\n        \"role\": \"user\",\n        \"parts\": [{\"kind\": \"text\", \"text\": \"hello\"}]\n      }\n    }\n  }'\n```\n\n### Connecting ovos-a2a-agent to this server\n\nOn another OVOS instance:\n\n```json\n{\n  \"name\": \"remote-persona\",\n  \"chat_module\": \"ovos-a2a-agent\",\n  \"ovos-a2a-agent\": {\n    \"url\": \"http://myhost:8337/a2a\"\n  }\n}\n```\n\n### A2A streaming\n\nThe A2A endpoint supports `message/stream`. Persona sentence chunks are emitted as `TaskArtifactUpdateEvent` SSE events. Enable streaming on the client side (e.g. `\"streaming\": true` in `ovos-a2a-agent` config).\n\n### A2A without `a2a-sdk`\n\nIf `a2a-sdk` is not installed and `--a2a-base-url` is provided, the server starts normally and logs a warning. All other API surfaces continue to work.\n\n---\n\n## Persona Config Examples\n\n### LLM persona (OpenAI-compatible backend)\n\n```json\n{\n  \"name\": \"gpt-persona\",\n  \"chat_module\": \"ovos-openai-plugin\",\n  \"ovos-openai-plugin\": {\n    \"api_key\": \"sk-...\",\n    \"model\": \"gpt-4o-mini\"\n  }\n}\n```\n\n### Knowledge-base + LLM fallback\n\n```json\n{\n  \"name\": \"smart-assistant\",\n  \"solvers\": [\n    \"ovos-solver-wikipedia-plugin\",\n    \"ovos-solver-ddg-plugin\",\n    \"ovos-solver-wordnet-plugin\",\n    \"ovos-openai-plugin\",\n    \"ovos-solver-failure-plugin\"\n  ],\n  \"ovos-openai-plugin\": {\n    \"api_key\": \"sk-...\",\n    \"model\": \"gpt-4o-mini\"\n  }\n}\n```\n\n### Rivescript chatbot (no GPU, no API key)\n\n```json\n{\n  \"name\": \"rivescript-bot\",\n  \"solvers\": [\n    \"ovos-solver-rivescript-plugin\",\n    \"ovos-solver-failure-plugin\"\n  ]\n}\n```\n\n---\n\n## Streaming\n\nAll seven non-A2A APIs support SSE streaming where the upstream spec defines it. Pass `\"stream\": true` (OpenAI / Cohere / TGI) or the equivalent for each API. See [docs/streaming.md](docs/streaming.md) for per-API details.\n\n---\n\n## OPM Tool Plugins — MCP and UTCP exposure\n\nInstalled `ToolBox` plugins (OPM entry-point group `opm.agents.toolbox`) are\nautomatically surfaced over two protocols when the server starts.\n\n### Installing the MCP extra\n\n```bash\npip install ovos-persona-server[mcp]\n```\n\nWithout the `[mcp]` extra only the UTCP endpoints are active.\n\n### UTCP — Universal Tool Calling Protocol\n\nTwo endpoints are added at `/tools`:\n\n| Method | Path | Description |\n|--------|------|-------------|\n| `GET`  | `/tools/manual` | Returns a UTCP manual JSON listing all tools |\n| `POST` | `/tools/{name}` | Invoke a tool by name with a JSON body |\n\n**Fetch the manual:**\n\n```bash\ncurl http://localhost:8337/tools/manual\n```\n\nResponse shape:\n\n```json\n{\n  \"utcp_version\": \"1.0\",\n  \"tools\": [\n    {\n      \"name\": \"my_tool\",\n      \"description\": \"Does something useful.\",\n      \"tool_provider\": {\n        \"type\": \"http\",\n        \"method\": \"POST\",\n        \"url\": \"http://localhost:8337/tools/my_tool\",\n        \"content_type\": \"application/json\"\n      },\n      \"inputs\": [\n        {\"name\": \"query\", \"type\": \"string\", \"required\": true, \"description\": \"Search query\"}\n      ],\n      \"output_schema\": { ... }\n    }\n  ]\n}\n```\n\n**Invoke a tool:**\n\n```bash\ncurl -X POST http://localhost:8337/tools/my_tool \\\n     -H \"Content-Type: application/json\" \\\n     -d '{\"query\": \"hello\"}'\n```\n\n### MCP — Model Context Protocol\n\nWhen the `[mcp]` extra is installed, the server mounts an MCP SSE endpoint at\n`/mcp`.  Each installed `ToolBox` tool is registered as an MCP tool with the\nname, description, and JSON Schema derived from its OPM definition.\n\n**Claude Desktop / MCP client config:**\n\n```json\n{\n  \"mcpServers\": {\n    \"ovos-persona-tools\": {\n      \"url\": \"http://localhost:8337/mcp/sse\"\n    }\n  }\n}\n```\n\n**Standalone stdio MCP server** (for clients that spawn a subprocess):\n\n```bash\novos-persona-tools-mcp\n```\n\nThis runs the same tool set over the stdio MCP transport.\n\n### Writing a ToolBox plugin\n\nImplement `ToolBox` from `ovos_plugin_manager.templates.agent_tools` and\nregister it under the `opm.agents.toolbox` entry-point group:\n\n```toml\n# pyproject.toml\n[project.entry-points.\"opm.agents.toolbox\"]\nmy_toolbox = \"my_package.toolbox:MyToolBox\"\n```\n\nThe server picks it up automatically on the next start.\n\n## Client side usage\n\nThe OpenAI and Ollama routers expose `/embeddings` endpoints. These require a solver plugin that implements `get_embeddings(text)`. If no such solver is loaded the endpoint returns HTTP 501. See [docs/embeddings.md](docs/embeddings.md).\n\n---\n\n## Authentication\n\nThe server itself does not enforce authentication — deploy behind a reverse proxy (nginx, Caddy, Traefik) with TLS and auth if public exposure is required. For the A2A endpoint, A2A clients that require bearer tokens can be configured on the client side (`api_key` in `ovos-a2a-agent` config).\n\n---\n\n## Troubleshooting\n\n**`Failed to load persona` (500 on startup)**\nThe persona JSON file was not found or is invalid. Check the `--persona` path and validate the JSON.\n\n**All requests return `500 Persona chat failed`**\nThe underlying solver chain failed. Check solver plugin installation and their individual configs (API keys, model paths, etc.).\n\n**A2A endpoint not available after starting with `--a2a-base-url`**\n`a2a-sdk` is not installed. Install it:\n```bash\nuv pip install 'ovos-persona-server[a2a]'\n```\nThen restart the server.\n\n**Embeddings return 501**\nNo solver with `get_embeddings()` is loaded. Add an embeddings solver to the persona's `solvers` list.\n\n**Legacy `/v1/` paths return responses with `Deprecation` header**\nThis is expected. Migrate to `/openai/v1/` paths. See [docs/deprecation.md](docs/deprecation.md).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopenvoiceos%2Fovos-persona-server","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fopenvoiceos%2Fovos-persona-server","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopenvoiceos%2Fovos-persona-server/lists"}