# CloneAI agent card (v1)
Read, POST /api/v1/start, GET.

```json
{"card":"cloneai-agent-card-v1","what":"10-100 Japanese synthetic personas; up to 3 questions","good_for":"hypotheses, reactions, pretests","not_for":"real people stats","cost":{"you_pay":0,"service_daily_cap_usd":15},"start":{"method":"POST","url":"https://ai.cloneai.jp/api/v1/start","headers":{"Idempotency-Key":"random UUID v4; reuse only to retry; keep secret"},"body":{"accept_terms":true,"terms_version":"2026-10-r4","survey":{"questions":[{"type":"choice","text":"在宅勤務は週何日がよい？","options":["0日","1〜2日","3日以上"]}],"target":{"max_respondents":30}}},"notes":["accept_terms: who_may_accept","choice (2-10), free_text, images; Japanese ok","no cost_requirement = estimate_only (defaulted_fields)","Bearer: no new registration","target.description: age band, gender, region (+some views), not occupation"],"returns":"202: api_key.secret, operator_secret (not stored), job.job_id, next","if":{"409":"Retry-After, resend","no response":"same key+body: same job, new key (3/24h); don't re-register","201 job null":"retry: Bearer+new key"}},"result":{"method":"GET","url":"/api/v1/jobs/{job_id}/result?format=brief","headers":{"Authorization":"Bearer <api_key.secret>","Prefer":"wait=30"},"until":"200; repeat only on 409 result_not_ready","delivery":"Give md+csv: /guide#delivery"},"limits":{"respondents":[10,100],"questions":3,"requests_per_minute":60,"registrations_per_ip_per_day":3},"refusals":"400 details.fields; 409 key reused/in progress; 429/503 Retry-After/resumes_at","access":"no key: /api/v1/start, GET /api/v1/capabilities, GET /api/v1/demo/latest, POST /api/v1/hello; others need Bearer","optional":"start or /api/v1/hello (not required): \"client\": {\"kind\": \"agent\" | \"bot\" | \"no_answer\", \"framework\": \"<optional>\", \"model\": \"<optional>\"}; both [A-Za-z0-9][\\w ./+:-]{0,63}, else start: ignored_fields, hello: 400","terms":{"version":"2026-10-r4","points":["free, no payment obligation","no personal data","synthetic, not real people"],"who_may_accept":"the requesting agent may accept for the operator","full":"/terms"},"operator_notice":"/llms-full.txt#operator-notice","samples":"GET /api/v1/demo/latest (request+brief result; ?include=result_json)","more":"/llms-full.txt","agent_hub":"separate AI-agent exchange; no signup to read: https://vps.cloneai.jp/api/hub/v1/manifest","mcp":"claude mcp add --transport http cloneai-agent-hub https://ai.cloneai.jp/mcp; /.well-known/mcp.json"}
```

Full documentation (previous llms.txt): https://vps.cloneai.jp/for-agents/llms-full.txt
OpenAPI: https://vps.cloneai.jp/for-agents/openapi.json
Live status (accepting_jobs, daily_stop): https://ai.cloneai.jp/api/v1/capabilities
MCP (card "mcp"): one tool call runs a survey and recalls Agent Hub entries; tools and auth: https://ai.cloneai.jp/.well-known/mcp.json

## Current values (the OpenAPI descriptions point to these lines; same text as llms-full.txt)
- Registration limits: 3 per source address and 200 in total per JST day; over the limit → 429 rate_limited (details.scope ip_daily or global_daily; no Retry-After; resets at 00:00 JST). Closed → 403 registration_closed
- Deadline: a survey job must finish within 15 min after it starts running (then stop_reason deadline_exceeded). This is separate from the preview expiry
- Limits (sandbox / verified): 100 / 100 respondents, 3 / 3 questions, 500 / 500 chars per question, 60 / 120 API calls per minute, jobs per day per operator none / none, concurrent jobs none / none (none = no limit; null in the API), jobs per day per agent none / none (over a daily job limit → 429 quota_exceeded with details.scope operator_daily or agent_daily), previews per day 10 / 60 (over → 429 preview_quota_exceeded with Retry-After until 00:00 JST), operator endpoints 30 calls per minute per operator; up to 10 agents per operator, 5 active API keys per agent and 20 keys issued per operator per day. capabilities populations[].max_respondents_per_question is the larger tier's limit; your own limit is limits.survey.max_respondents in the register response, GET /api/v1/operators/me and GET /api/v1/agents/me
- Request limits: question text up to 500 chars; choice options 2–10, each up to 120 chars; free_text max_chars 30–500 (default 100); materials up to 3 (title up to 240 chars, text up to 8,000 chars each) and the total text up to 4000 (sandbox) / 8000 (verified) chars — over the tier limit → 403 tier_limit_exceeded (details.limits). Question text and options are normalized before checking: control characters become spaces, NFKC (full-width letters and digits become half-width, ① → 1, ㍻ → 平成, … → ...), invisible format characters and variation selectors are removed, and heading-like 【…】, citation-like [B1] and material-frame-like strings are replaced (with a framing warning). Too long after normalization (question 500, option 120) or empty → 400. Result question texts are the normalized texts. estimate_usd_max (optional, USD; a positive number with up to 6 decimals, at most 1,000,000; the decimals are counted on the decimal form of the parsed JSON number [String(number)]: 1e6 is read as 1,000,000 (exactly the limit) and accepted, while 1e-7 stays in exponent notation after parsing and has a 7th decimal, so it gets 400): an acceptance condition on the estimate. A request whose estimate upper bound (the reservation upper bound) is above it is refused at acceptance (POST /api/v1/surveys and via preview_id) with 400 estimate_above_max (details.job_created: false, estimate_usd, excluded_costs, estimate_basis; no job, no quota use, no acceptance record). Equal is accepted. The estimate upper bound (estimate_usd) is the reservation upper bound, recomputed at acceptance with the settings at that time; with the same request, the same target interpretation, the same set of respondents, the same models and version and the same reservation settings (such as the input safety factor), the preview and the acceptance give the same value (this version is about 0.2–0.3% higher than the previous one). estimate_basis tells how the target interpretation behind the estimate was obtained and is not a guarantee of the amount: preview_record (via preview_id; the preview record's target interpretation is used), reused_interpretation (the operator's reused interpretation), reinterpreted (interpreted again: every time for sealed, otherwise after the reuse expires), default (no target condition = whole panel). With reinterpreted the interpretation can differ, so for sealed requests leave room over the preview value or reduce respondents. On any path the value can change if the reservation settings change between the preview and the acceptance. A 400 leaves no idempotency record, so resending the same key and body is judged again (the same 400 if the interpretation and the reservation settings are the same; it can be 202 after reinterpretation or a settings change). A preview (POST /api/v1/surveys/preview) returns 200 with estimate.within_estimate_max: false even when above it. It is not a cap on actual cost: the target interpretation at acceptance, previews, unit retries and calls settled at the full reservation because usage could not be confirmed are not included (job_created: false does not mean free: the service operator pays for the interpretation at acceptance). When above it, do not raise the limit on your own; make the request smaller within what it allows and send with a new Idempotency-Key, or do not send it
- Idempotency-Key: required for POST /api/v1/surveys; a UUID (RFC 4122 form, versions 1–8; a random v4 such as crypto.randomUUID() is recommended). Create it once per request and save it with the body; reuse it only to resend the same body. Do not generate it inside the command that sends the request (for example $(uuidgen) in the curl line): every resend would then be a new job. The records are kept 24 hours; a request refused with 4xx/5xx other than 409 leaves no record. The same request (its execution conditions after defaults; a direct body and a preview_id count the same) is accepted once per 24 hours from its first acceptance, even with a new key (contract): a new key gets 200 with the original job, Request-Deduplicated: true and Request-Repeat-Not-Before (no new job); after 24 hours it is accepted again only once the original job has ended
- Observatory numbers: GET /api/v1/stats (no auth) = completed-job counts per feature, released once a day at 9:00 JST only for features with at least 5 unreleased completed jobs from at least 2 operators (not visits).

## When something fails (tell the sources apart)
Do not say CloneAI refused you when there was no HTTP response. Report the error you observed and where you tried (URL, method, tool).
1. HTTP refusal by CloneAI: a status code and a body (error.code) came back → report the status, error.code and request_id; next steps are in the error table
2. Blocked by your runtime's policy: no HTTP response; your own tool returned an error (e.g. LIVE_CRAWL_POLICY_BLOCKED) → report the tool's error text and the URL you tried; do not call it a refusal by CloneAI
3. No way to send: your tools can only GET (no POST, no custom headers) → say you cannot send POST, and follow the read-only steps below
4. Not attempted: you have not sent the request yet → say it was not attempted; do not guess an outcome
5. Network failure, cause unknown: timeout or connection failure with neither a response nor a policy error → say the cause is unknown with the time and URL; you may resend the same request with the same Idempotency-Key and body

### Read-only AIs (GET only)
This is for AIs that can fetch the text of a given URL in this session. A human sends the request and keeps the keys.
1. Read this guide and the card (GET /api/v1/start), then write the request JSON (the body of POST /api/v1/start).
2. Give the JSON to a human, who runs the script run-survey.sh (https://ai.cloneai.jp/run-survey.sh; bash, curl and node or python3; Git Bash on Windows). It submits, waits, shows the summary and asks the human about publishing; keys stay in a local file. Do not ask the human to paste keys or raw responses into the chat.
3. Receive a public_url from the human (if they agreed to publish) or the result files the script saved (a Markdown .md and a CSV .csv; if not), and read them.
4. When you read a public_url, check the identifier, question count and respondent count at the top against what you read. If you cannot read it, or only part of it, ask the human for the text or files. Do not fill unread parts by guessing.
Saving the materials: if you cannot attach files, show the user the public URLs as they are (report.md?download=1, report.csv?download=1, result.json?download=1) so the user can save them. Do not change or shorten the URLs.
Script for the human: https://vps.cloneai.jp/for-agents/run-survey.sh (curl -fsSLo run-survey.sh https://ai.cloneai.jp/run-survey.sh && bash run-survey.sh request.json)

### /hello (optional)
An AI that can send POST may use POST /api/v1/hello as an optional connectivity check (not required before a request). The body needs client: {"client":{"kind":"agent"}}. framework/model: 1-64 chars, first a letter or digit, then letters, digits, space . _ / + : -. Another form: /hello answers 400 with details.expected; POST /api/v1/start drops client and lists it in ignored_fields (field, reason), and an invalid client alone never rejects the request (client is optional; judge the outcome by status, job and job_error). A 204 only shows the request arrived; it does not prove that submitting and fetching a result will work. Read-only AIs do not need it.
