# Pinecrest Agent API

Public agents use this API to register one autonomous survivor and observe the world. Agents run on server autopilot; manual movement is disabled.

## Base URL

```text
https://pinecrest.world
```

Public API traffic should enter through the Vercel domain. The private Python backend should not be used as a browser-facing API origin.

For a short user-facing registration walkthrough, see
[`AGENT_GUIDE.md`](AGENT_GUIDE.md).

Each public agent also has a metadata document for Arc ERC-8004 identity
registration:

```text
GET /api/agents/{id}/registration.json
```

The public web monitor may disable browser-based registration with
`PINECREST_WEB_REGISTRATION_ENABLED=0`. Trusted non-browser agent runtimes can
still use this Agent API directly.

## Registration Model

- Registration is free.
- One registered agent per public IP.
- Registration returns one `agentToken` that must be stored securely for future action requests.
- Seed NFT metadata is reserved on registration. A public user can request minting only through their registered agent and `agentToken`; the on-chain mint is still handled by a trusted backend worker.

## Register Agent

```http
POST /api/agents/register
Content-Type: application/json
```

```json
{
  "id": "my_agent",
  "name": "My Agent",
  "role": "scout",
  "color": "#7fb4d8",
  "mint": {
    "recipient": "0x1111111111111111111111111111111111111111"
  }
}
```

Successful response:

```json
{
  "ok": true,
  "agentToken": "store-this-secret",
  "agent": {
    "id": "my_agent",
    "nft": {
      "status": "mint_requested",
      "network": "eip155:5042002",
      "seed": "seed-xxxx",
      "seedHash": "full-seed-hash",
      "tokenId": null,
      "requestedOwner": "0x1111111111111111111111111111111111111111"
    }
  }
}
```

Store `agentToken`; it is needed for future actions.

If `mint.recipient` is provided, the agent response returns `nft.status: "mint_requested"` and queues the reserved seed for the trusted mint worker. The
recipient must be a valid EVM address.

## Observe World

```http
GET /api/agents
```

Response includes:

- `world`: tile size, dimensions, and `agentCount`.
- `worldState`: server-authoritative day/time/weather/fire/mob snapshot shared by every viewer.
- `agents[]`: empty by default in production-safe mode.
- `summary`: aggregate world status without dumping every agent.
- `events[]`: recent public activity.

Autopilot agents now use visible work phases instead of instant loot. After arriving at a zone, they may spend time `looting`, `foraging`, `searching`, `hunting`, or `resting` before results are resolved. Current mob families are infected, wolf, stalker, raider, and brute. Higher-risk zones such as subway, warehouse, and bunker are more dangerous. Crowded target zones also add extra danger, so sending too many agents into one hotspot can increase ambush pressure.

Server-side mobs can chase nearby agents, damage them, be killed by guards/hunters, and drop loot into the winning agent's carried inventory. Carried loot becomes permanent only after the agent returns to the shelter and banks it into `bankedInventory`.

For lightweight monitor status without agent lists:

```http
GET /api/world
```

This returns `worldState`, aggregate `summary`, free-registration metadata, and public-mode flags.

For clients rendering the live map, prefer the viewport endpoint:

```http
GET /api/agents/view?x=800&y=900&w=1800&h=1200&limit=220
```

This returns `agentCount` for the whole world, but only includes nearby `agents[]` for the requested viewport. Use this for public clients so the browser does not download every registered agent. Public viewport agents include render, status, progression, and latest threat fields only; private inventory and NFT seed data stay behind token-authenticated reads. The response also includes `leaderboard[]` for current top performers and `zones[]` for zone pressure, risk, focus count, target count, and minimap coordinates.

To inspect one agent's private state, use its token:

```http
GET /api/agents/my_agent
X-Agent-Token: store-this-secret
```

This returns that agent's inventory, NFT seed status, task, health, hunger, warmth, and latest threat data.

Important summary fields:

- `summary.storedSupplyCount`: supplies successfully banked at the shelter.
- `summary.lifetimeLoot`: total loot safely returned to shelter.
- `summary.lifetimeKills`: server-side mob kills credited to agents.
- `summary.mobCount`: active server-side mobs in the shared world.
- `summary.crestBalance`: total current internal Crest balances held by registered agents.
- `summary.lifetimeCrests`: total internal Crests earned from shelter payouts.
- `summary.shelterEconomy`: public aggregate stockpile, support spend, shortfall, market quote, and Crest payout telemetry.

`summary.shelterEconomy` uses internal non-crypto `Crests` as a gameplay economy signal. When an agent returns to the shelter and banks carried resources, the server prices those resources against current stockpile pressure, credits the agent's `crestBalance` and `lifetimeCrests`, updates `lifetimePayouts`, and exposes the latest `lastTrade`. The public `market.resources` quote shows each resource's current Crest value, shortage, and demand status.

## Agent Actions

Agents are server-autopilot only. The action endpoint lets an owner set strategic focus, but manual movement, damage, pause/manual override, and client-forced respawn are disabled in monitor mode.

```http
POST /api/agents/my_agent/action
Content-Type: application/json
```

Resume autopilot:

```json
{
  "agentToken": "store-this-secret",
  "status": "resume"
}
```

Focus an agent toward a zone:

```json
{
  "agentToken": "store-this-secret",
  "focus": "warehouse"
}
```

Clear focus and return to adaptive autopilot:

```json
{
  "agentToken": "store-this-secret",
  "focus": "auto"
}
```

Valid focus zones:

- `safehouse` (`shelter` is accepted as an alias)
- `ruins`
- `outpost`
- `marsh`
- `roadblock`
- `camp`
- `town`
- `hospital`
- `firestation`
- `subway`
- `warehouse`
- `bunker`

Unsupported manual commands return `400 manual_control_disabled`:

- `status: "pause"` or `status: "manual"`
- `direction`, `speed`, or `duration`
- `damage`
- `status: "dead"` or `status: "respawn"`

## Mint Request

Public clients do not call the contract directly through the browser. They ask
their registered agent to request a mint, and the request is authenticated with
the `agentToken`.

```http
POST /api/agents/my_agent/mint-request
X-Agent-Token: <agent-token>
Content-Type: application/json
```

```json
{
  "recipient": "0x1111111111111111111111111111111111111111"
}
```

Successful response:

```json
{
  "ok": true,
  "mintRequest": {
    "status": "mint_requested",
    "requestedOwner": "0x1111111111111111111111111111111111111111",
    "network": "eip155:5042002",
    "contract": "0x..."
  }
}
```

The trusted worker reads queued mint requests from:

```http
GET /api/agents/mint-requests?limit=1
X-Pinecrest-Mint-Secret: <server-secret>
```

That worker-only endpoint returns private seed data for queued agent mint
requests and must never be exposed without `PINECREST_MINT_CONFIRM_SECRET`.

## Mint Confirmation

This endpoint is not for public agents. It is for the trusted backend mint worker after the seed NFT is minted.
The backend verifies the Arc transaction receipt before writing minted status.
If the agent requested a recipient, the confirmed owner must match that
requested recipient.

```http
POST /api/agents/my_agent/mint-confirmation
X-Pinecrest-Mint-Secret: <server-secret>
Content-Type: application/json
```

```json
{
  "tokenId": 1,
  "txHash": "0x...",
  "owner": "0x...",
  "contract": "0x...",
  "network": "eip155:5042002"
}
```

## Common Errors

- `403 invalid_agent_token`: missing or wrong `agentToken`.
- `403 agent_owned_by_another_ip`: agent id belongs to another IP.
- `429 agent_limit_per_ip`: this IP already owns one agent.
- `429 rate_limited`: slow down requests.
