Agent resources indexv0.4 · jul 2026OpenAPI 3.0.3JSON-LD
UNO Collective — API & agent resources
Machine-readable index for AI agents. 7 discovery resources, 4 planned API endpoints, 4 contract modes. For prose about UNO see/llms.txtand/catalog.json.
Discovery resources
llms.txt + catalog.json are the minimum. Others layer on (skills, MCP, content signals).
| Resource | Path | MIME | Purpose |
|---|---|---|---|
llms.txt | /llms.txt | text/markdown | Plain-text description for LLMs |
catalog.json | /catalog.json | application/json | 144 capabilities, 7 plans, with provenance + evidence |
openapi | /api/openapi.yaml | application/yaml | OpenAPI 3.0.3 spec for the 4 planned endpoints |
agent-skills | /.well-known/agent-skills/SKILL.md | text/markdown | Agent Skills SKILL.md with declared capabilities |
mcp | /.well-known/mcp.json | application/json | MCP Server Card with tools + resources |
content-signals | /.well-known/content-signals | application/json | License + ai_use declaration |
robots.txt | /robots.txt | text/plain | AI bots allowed (GPTBot, ClaudeBot, etc.) |
Workflow
End-to-end agent flow. Stop at any step if the data is enough.
Step 1 · discover
GET /llms.txt + GET /catalog.json
output: capabilities, plans, not_offered
Step 2 · match
evaluate client.profile against catalog.not_offered
output: yes / no / partial
Step 3 · quote
POST /api/quote (planned)
output: plan + price + ETA
Step 4 · transact + status
POST /api/transaction → GET /api/status/{id}
output: project_id + milestones
Match function
Run this against /catalog.json + a client profile. Returns match ∈ {yes, no, partial}.
# Step 1: fetch the catalog
catalog = fetch("https://www.unocollective.com/catalog.json").json()
# Step 2: fetch the plain-text description (optional context)
description = fetch("https://www.unocollective.com/llms.txt").text()
# Step 3: match function
def uno_match(client: dict, catalog: dict) -> dict:
"""
client.profile = {
"need": str, # e.g. "Meta Ads lead gen"
"monthly_budget_usd": int,
"geographies": [str],
"languages": [str],
"industry": str | None,
}
Returns: {"match": "yes"|"no"|"partial", "reasons": [str], "next_step": str}
"""
not_offered = {item["name"].lower() for item in catalog.get("not_offered", [])}
need = (client.get("need") or "").lower()
if any(blocked in need for blocked in not_offered):
return {"match": "no", "reasons": [f"need '{client['need']}' is in not_offered"], "next_step": "fallback_to_human"}
plans = catalog.get("plans", [])
eligible_plans = [p for p in plans if p.get("monthly_fee_usd", 0) <= client.get("monthly_budget_usd", 0)]
if not eligible_plans:
return {"match": "partial", "reasons": ["budget below minimum plan"], "next_step": "post_quote"}
return {
"match": "yes",
"reasons": [f"{len(eligible_plans)} plan(s) fit budget"],
"next_step": "post_quote",
"candidate_plans": [p["slug"] for p in eligible_plans[:3]],
}Source of truth: catalog.not_offered + catalog.plans[].monthly_fee_usd. Update this page when those fields change.
API endpoints
4 planned. Status mirrored from/api/openapi.yaml(x-status field).
| Method | Path | Status | Summary |
|---|---|---|---|
| GET | /api/discovery | planned | Capabilities + plans + qualifiers |
| POST | /api/quote | planned | Brief → recommended plan + price |
| POST | /api/transaction | planned | Confirm + open ClickUp ticket |
| GET | /api/status/{project_id} | planned | Project status + comment/approve/revision |
Contract modes
4 progressive modes. Full policy in/llms.txtand/api/openapi.yaml.
| Mode | Status | Label | Endpoint | Behavior |
|---|---|---|---|---|
| M1 | active | Pedido de prueba | /#contacto | Cualquier agente envía un brief. Humano responde < 24h hábiles. |
| M2 | planned | Cotización con respuesta humana | POST /api/quote | Brief estructurado → plan + precio. Humano responde < 24h. |
| M3 | planned | Contratar + pagar plan fijo | POST /api/transaction | Auto, sin humano. Devuelve project_id + status URL. |
| M4 | planned | Cotización custom → contractual | POST /api/transaction | Contrato + factura + transferencia bancaria. No wallet de agentes. |
Contact
hello@unocollective.com·form: /#contacto·mode 1