# Agivo: instructions for tool-enabled agents

Base URL: https://agivo.app
Protocol: ordinary HTTPS + JSON + binary PUT. No model-provider SDK, Hermes installation, or agent registration is required. Agents need HTTP tools and access to file bytes, or a terminal with Node.js 20+ and curl. Text-only agents cannot upload files. This is static hosting, not SSR, server functions, databases, or background jobs. Build static output locally first.

## Choose an interface
- [Existing CLI skill](https://agivo.app/skill.md)
- [Download standalone CLI](https://agivo.app/agivo.mjs)
- [Publishing OpenAPI](https://agivo.app/openapi.json) (publishing subset, not every management endpoint)
- [Human documentation](https://agivo.app/docs), [Terms](https://agivo.app/terms), [Privacy](https://agivo.app/privacy)

CLI (review downloaded code before executing):
```sh
curl -fsSL https://agivo.app/agivo.mjs -o /tmp/agivo.mjs
node /tmp/agivo.mjs publish ./dist
```
For account-owned publishing, inject AGIVO_TOKEN through your private runtime secret mechanism. Do not put it in command arguments, chat, source files or shell history. AGIVO_URL defaults to https://agivo.app. Updates use the same command with --slug YOUR_OWNED_SLUG. Use --spa only for client-side routing, not SSR. No package installation or provider plugin is necessary. The optional /install.sh installs a Markdown skill to ~/.agents/skills/agivo; that directory is a convention, not a promise that every agent auto-loads it. Any agent can simply read these instructions.

## Bare HTTP workflow
1. Inspect the output folder. Remove secrets, .env, keys, databases, private data and unsafe source maps. The CLI does not perform a complete secret scan. Obtain user permission to publish.
2. POST /api/v1/publish with Content-Type: application/json and a files array. Each entry contains path (relative POSIX path), size (byte length), contentType, and preferably hash (lowercase SHA-256 of exact bytes). Optional slug requests a name; omit to generate one. Example manifest for an empty file: {"files":[{"path":"empty.txt","size":0,"contentType":"text/plain"}]}. Upload actual generated files in normal use.
3. No Authorization header creates a temporary anonymous project. For an account, send Authorization: Bearer with the privately supplied API token on create and finalize. Validate account identity with GET /api/me before an authenticated workflow: an invalid token may otherwise be treated as anonymous by the existing create endpoint. Stop on failed identity checks rather than silently publishing anonymously.
4. Keep the 201 response private. It contains slug, siteUrl, upload.versionId, upload.finalizeToken, upload.finalizeUrl, upload.uploads and upload.skipped. Anonymous creation also returns claimUrl, claimToken and expiresAt. Resolve relative URLs against the base URL; check the origin before transmitting credentials. Do not invent upload URLs.
5. For each upload.uploads item, PUT the exact raw file bytes to its returned url, using its method and headers (including the exact Content-Type). Expect 204. Do not send base64 or multipart. Skip only paths listed in upload.skipped. Upload URLs contain capabilities: redact the entire URL from traces, telemetry, tool transcripts and error reports. PUT is not guaranteed idempotent: do not blindly retry an already-written upload.
6. POST upload.finalizeUrl with JSON {"versionId": <returned versionId>} and X-Agivo-Finalize: <returned finalizeToken>. For account-created stages also send the same account authorization. Expect 200 and success:true. Read siteUrl and currentVersionId from the response. Create alone does not make a deployment live.
7. GET the returned siteUrl (and representative assets) and verify the expected content before telling the user it is live. Password-protected content requires the intended viewer flow; HTTP 401 is not public verification. No management API exists on tenant subdomains.
8. Return the actual live URL. Deliver the exact anonymous claimUrl only through a private user channel; never place it in public content, shared logs or analytics. Preserve its fragment. The existing CLI prints the private claim URL, so disable shared output capture or use bare HTTP when your tools log stdout.

## Keep, then update
Anonymous projects expire at the returned expiresAt, normally 24 hours from stage creation; a shorter ttlSeconds is allowed, never longer than 86400. Claim before expiry. Open the exact claim link privately and let the human sign up/log in and complete consent and CAPTCHA. Never bypass or automate solving CAPTCHA. In the dashboard the human creates an API token for the agent. API tokens cannot mint new API tokens.

An already authenticated account may POST /api/v1/publish/{slug}/claim with JSON claimToken and its bearer token. Claim capability plus account authentication and quota checks are required. Anonymous projects cannot be updated until claimed, even with a new account token. After claiming, repeat create/upload/finalize with the same slug and a complete manifest. Omitted files are removed in the new version. Matching hash AND size can skip uploads. Each finalized update creates a retained version. Account ownership removes temporary expiry; it is not a guarantee of perpetual service.

## Limits and errors
- Default deployment limit: 20 MiB, 1–1000 files. Manifest body: 1 MiB; finalize/claim body: 4096 bytes. Stage upload/finalize window: one hour. Deployment size is configurable; do not assume unlimited authenticated uploads.
- Anonymous create: 10 requests/minute per server-observed IP; shared pending-stage capacity: 100 stages / 200 MiB. Edge rate limits may be stricter. Account quotas cover projects, retained versions, stored bytes and pending reservations; GET /api/usage returns the actual account limits and usage. Do not multiply tokens to evade account limits.
- API errors normally have {"error":"message"}; proxy errors can be HTML. Check status and Content-Type before parsing. 400 invalid input/size/hash; 401 missing or changed identity; 403 capability/ownership denial or claim required; 404 missing resource; 408 body deadline; 409 concurrent state change; 410 expired project; 413 request/deployment too large; 429 rate limit (account quota exhaustion returns 409); 503 anonymous capacity; 500 unexpected failure.
- Back off on 429/503, honor Retry-After when present, and do not retry forever. On 409 re-read state and restart with user approval if needed. On missing/expired stage, start a new stage rather than fabricate a result. Finalize replay requires its capability and applicable account identity; stage cleanup can make replay return 404.

## Evidence and compatibility boundary
Bare HTTP is the provider-neutral interface. No special compatibility certification for Claude, Codex, Gemini or other providers is claimed. Hermes publishing was user-reported and its resulting URL was independently checked; this release tests the HTTP lifecycle in disposable fixtures, not those other products. Tool permissions, network access, secret handling and static build support remain prerequisites.
