Skip to main content

create-api-test-script

Create backend test scripts for app skills or providers that need Vault secrets inside the api Docker container

Jump to install

Source facts

Repository
glowingkitty/OpenMates
Last source activity
June 4, 2026 at 11:03
Detected SKILL.md language
English
Stars
46
Forks
3

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
create-api-test-script
description
Create backend test scripts for app skills or providers that need Vault secrets inside the api Docker container
user-invocable
true
argument-hint
<app>/<skill> or <provider>
## Arguments Parse `$ARGUMENTS` as the target to test, such as `web/search`, `images/search`, `brave`, or `context7`. If the target is missing or ambiguous, ask which app skill or provider the script should exercise. ## Instructions You are creating a manual backend API/app-skill test script that may need Vault-backed provider secrets. Use this workflow for quick probes, provider evaluations, and reproducible integration checks that are not part of the normal pytest suite. ### Step 1: Choose The Script Location Put Vault-dependent scripts under `backend/scripts/` so they are available inside the running `api` container as `/app/backend/scripts/<script>.py`. Do not put Vault-dependent scripts under `scripts/api_tests/` unless the script is intentionally host-only. The repo-level `scripts/` directory is not mounted into the `api` container by default, so those scripts cannot directly use `/vault-data/api.token` or the container runtime environment. ### Step 2: Choose The Execution Path Use the path that matches what you are testing: | Test target | Recommended path | Why | |-------------|------------------|-----| | App skill behavior | `SkillRegistry.dispatch_skill()` | Matches the in-process app-skill architecture used by API and workers | | Provider wrapper behavior | Direct provider import + `SecretsManager` | Isolates provider auth, request, parsing, and errors | | Public REST API contract | Authenticated `/v1/apps/{app}/skills/{skill}` | Tests external API auth, billing, and response envelope | Avoid old per-app container endpoints such as `http://app-web:8000/skills/search`. Apps now load in-process inside `api` and Celery workers. ### Step 3: Use The Container Command Run Vault-dependent scripts with: ```bash docker exec api python /app/backend/scripts/<script>.py ``` Use `python`, not host `python3`, when documenting the in-container command. The script itself may use a `#!/usr/bin/env python3` shebang, but the command should be explicit and container-local. ### Step 4: App Skill Script Template Use this when testing the actual app skill dispatch path: ```python #!/usr/bin/env python3 """ Purpose: Test <app>/<skill> through the in-process app skill registry. Architecture: Runs inside the api container where Vault and backend apps are available. Data sources: Existing OpenMates app skill and its configured providers. Tests: Manual CLI verification with small, low-cost sample requests. Usage: docker exec api python /app/backend/scripts/test_<app>_<skill>.py """ from __future__ import annotations import asyncio import json import logging import sys from typing import Any from backend.core.api.app.services.skill_registry import build_skill_registry APP_ID = "<app>" SKILL_ID = "<skill>" def summarize_response(response: dict[str, Any]) -> dict[str, Any]: results = response.get("results") or [] first_group = results[0] if results else {} first_items = first_group.get("results") or [] if isinstance(first_group, dict) else [] return { "provider": response.get("provider"), "error": response.get("error"), "group_count": len(results), "result_count": len(first_items), "first_title_present": bool(first_items and first_items[0].get("title")), } async def main() -> int: logging.basicConfig(level=logging.WARNING) registry, metadata = build_skill_registry() if APP_ID not in metadata: print(json.dumps({"status": "fail", "error": f"app not loaded: {APP_ID}"})) return 1 if not registry.is_skill_available(APP_ID, SKILL_ID): print(json.dumps({"status": "fail", "error": f"skill not available: {APP_ID}/{SKILL_ID}"})) return 1 response = await registry.dispatch_skill( APP_ID, SKILL_ID, {"requests": [{"id": "probe", "query": "OpenMates open source AI assistant", "count": 1}]}, ) summary = summarize_response(response) status = "pass" if summary["result_count"] > 0 and not summary["error"] else "fail" print(json.dumps({"status": status, **summary}, ensure_ascii=False)) return 0 if status == "pass" else 1 if __name__ == "__main__": sys.exit(asyncio.run(main())) ``` Adjust request fields to the target skill's `tool_schema`. For non-search skills, keep the summary similarly small and non-sensitive. ### Step 5: Provider Script Template Use this when testing a provider wrapper directly: ```python #!/usr/bin/env python3 """ Purpose: Test the <provider> provider wrapper with Vault-backed credentials. Architecture: Runs inside the api container and uses SecretsManager. Data sources: External <provider> API through backend/shared/providers. Tests: Manual CLI verification with one low-cost sample request. Usage: docker exec api python /app/backend/scripts/test_<provider>_provider.py """ from __future__ import annotations import asyncio import json import sys from backend.core.api.app.utils.secrets_manager import SecretsManager async def main() -> int: secrets_manager = SecretsManager() await secrets_manager.initialize() try: # Import and call the provider here. Keep counts small. # Never print secrets, prefixes, lengths, tokens, or raw auth headers. result = {"replace": "with provider result"} finally: await secrets_manager.aclose() print(json.dumps({"status": "pass", "result": result}, ensure_ascii=False)) return 0 if __name__ == "__main__": sys.exit(asyncio.run(main())) ``` ### Step 6: Output Rules Print only non-sensitive verification data: - `status`: `pass` or `fail` - provider name - result counts - selected non-sensitive fields, such as whether a title or URL is present - error messages that do not include credentials Do not print: - API keys, tokens, OAuth credentials, cookies, or Vault values - key prefixes, suffixes, lengths, masked values, or auth headers - private user data or raw logs with identifiers - large raw provider payloads unless the user explicitly needs a fixture and the payload is reviewed for sensitive content If saving fixtures, write them under `backend/scripts/results/` or another explicit non-source output directory, and keep them out of commits unless the user asks to add sanitized fixtures. ### Step 7: Verify Run the script in the `api` container: ```bash docker exec api python /app/backend/scripts/<script>.py ``` If it fails because the provider is rate-limited or unavailable, report that separately from script correctness. Do not increase request counts to brute-force provider failures. ### Step 8: Cleanup And Commit Scope Before committing, ensure the commit includes only the script and any intentional docs/skill changes. Do not commit generated result JSON unless it is a sanitized fixture requested by the user. ## Rules - New `.py` scripts need a 5-10 line file header comment or docstring. - Default to the smallest possible external request count, usually `count=1`. - Use `asyncio` and `httpx`-based provider code; do not add `requests`. - Prefer `SkillRegistry.dispatch_skill()` for app-skill tests. - Prefer direct provider calls only for provider-specific tests. - Never use old `app-{id}:8000/skills/...` endpoints for new scripts. - Never expose secrets or partial secrets in logs, output, fixtures, or comments.
View on GitHub