* feat(agent-readiness): Agent Skills discovery index (#3310) Closes #3310. Ships the Agent Skills Discovery v0.2.0 manifest at /.well-known/agent-skills/index.json plus two real, useful skills. Skills are grounded in real sebuf proto RPCs: - fetch-country-brief → GetCountryIntelBrief (public). - fetch-resilience-score → GetResilienceScore (Pro / API key). Each SKILL.md documents endpoint, auth, parameters, response shape, worked curl, errors, and when not to use the skill. scripts/build-agent-skills-index.mjs walks every public/.well-known/agent-skills/<name>/SKILL.md, sha256s the bytes, and emits index.json. Wired into prebuild + every variant build so a deploy can never ship an index whose digests disagree with served files. tests/agent-skills-index.test.mjs asserts the index is up-to-date via the script's --check mode and recomputes every sha256 against the on-disk SKILL.md bytes. Discovery wiring: - public/.well-known/api-catalog: new anchor entry with the agent-skills-index rel per RFC 9727 linkset shape. - vercel.json: adds agent-skills-index rel to the homepage + /index.html Link headers; deploy-config required-rels list updated. Canonical URLs use the apex (worldmonitor.app) since #3322 fixed the apex redirect that previously hid .well-known paths. * fix(agent-readiness): correct auth header + harden frontmatter parser (#3310) Addresses review findings on #3310. ## P1 — auth header was wrong in both SKILL.md files The published skills documented `Authorization: Bearer wm_live_...`, but WorldMonitor API keys must be sent in `X-WorldMonitor-Key`. `Authorization: Bearer` is for MCP/OAuth or Clerk JWTs — not raw `wm_live_...` keys. Agents that followed the SKILL.md verbatim would have gotten 401s despite holding valid keys. fetch-country-brief also incorrectly claimed the endpoint was "public"; server-to-server callers without a trusted browser origin are rejected by `validateApiKey`, so agents do need a key there too. Fixed both SKILL.md files to document `X-WorldMonitor-Key` and cross-link docs/usage-auth as the canonical auth matrix. ## P2 — frontmatter parser brittleness The hand-rolled parser used `indexOf('\n---', 4)` as the closing fence, which matched any body line that happened to start with `---`. Swapped for a regex that anchors the fence to its own line, and delegated value parsing to js-yaml (already a project dep) so future catalog growth (quoted colons, typed values, arrays) does not trip new edge cases. Added parser-contract tests that lock in the new semantics: body `---` does not terminate the block, values with colons survive intact, non-mapping frontmatter throws, and no-frontmatter files return an empty mapping. Index.json rebuilt against the updated SKILL.md bytes.
2.9 KiB
name, version, description
| name | version | description |
|---|---|---|
| fetch-country-brief | 1 | Retrieve the current AI-generated strategic intelligence brief for a country, keyed by ISO 3166-1 alpha-2 code. |
fetch-country-brief
Use this skill when the user asks for a summary of the current geopolitical, economic, or security situation in a specific country. The endpoint returns a fresh AI-generated brief composed from the latest news, market, conflict, and infrastructure signals World Monitor tracks for that country.
Authentication
Server-to-server callers (agents, scripts, SDKs) MUST present an API key in the X-WorldMonitor-Key header. Authorization: Bearer … is for MCP/OAuth or Clerk JWTs — not raw API keys.
X-WorldMonitor-Key: wm_live_...
Browser requests from worldmonitor.app get a free pass via CORS Origin trust, but agents will never hit that path. Issue a key at https://www.worldmonitor.app/pro.
Endpoint
GET https://api.worldmonitor.app/api/intelligence/v1/get-country-intel-brief
Parameters
| Name | In | Required | Shape | Notes |
|---|---|---|---|---|
country_code |
query | yes | ISO 3166-1 alpha-2, uppercase (e.g. US, IR, KE) |
Case-sensitive server-side. Lowercase is rejected with 400. |
framework |
query | no | free text, ≤ 2000 chars | Optional analytical framing appended to the system prompt (e.g. "focus on energy security"). |
Response shape
{
"countryCode": "IR",
"countryName": "Iran",
"brief": "Multi-paragraph AI-generated brief …",
"model": "gpt-4o-mini",
"generatedAt": 1745421600000
}
generatedAt is Unix epoch milliseconds. model identifies which LLM produced the text.
Worked example
curl -s -H "X-WorldMonitor-Key: $WM_API_KEY" \
'https://api.worldmonitor.app/api/intelligence/v1/get-country-intel-brief?country_code=IR' \
| jq -r '.brief'
With an analytical framework:
curl -s --get -H "X-WorldMonitor-Key: $WM_API_KEY" \
'https://api.worldmonitor.app/api/intelligence/v1/get-country-intel-brief' \
--data-urlencode 'country_code=TR' \
--data-urlencode 'framework=focus on energy corridors and Black Sea shipping'
Errors
400—country_codemissing, not 2 letters, or not uppercase.401— missingX-WorldMonitor-Key(server-to-server callers).429— rate limited; retry with backoff.5xx— transient upstream model failure; retry once after 2s.
When NOT to use
- For rankings or comparisons across countries, use
fetch-resilience-scoreper country and aggregate client-side, or call theGetResilienceRankingRPC directly. - For raw news events rather than synthesized narrative, use
SearchGdeltDocuments(/api/intelligence/v1/search-gdelt-documents).
References
- OpenAPI: IntelligenceService.openapi.yaml — operation
GetCountryIntelBrief. - Auth matrix: https://www.worldmonitor.app/docs/usage-auth
- Documentation: https://www.worldmonitor.app/docs/documentation