# Agent API (organizations)

> Expose an organization agent the way Dify exposes an app — one agent key on /v1/chat/completions automatically applies that agent's persona, locked model, capability switches and attached knowledge bases

来源：https://zhonkemodel.dflop.top/en/docs/reference/agent-api

On [zhonkemodel.dflop.top](https://zhonkezhonkemodel.dflop.top), an organization can create **agents**: a preset persona (system prompt), a locked model, web-search and image-generation switches, and attached knowledge bases. The **Agent API** exposes one agent much like a Dify "app" — you get an API key bound to that agent, call it with the standard OpenAI protocol, and the backend applies the agent's entire configuration for you.

> One agent key = one agent. The caller **doesn't need to know** the persona, model or knowledge bases — those come from the agent's configuration, and the client only sends conversation content.

| | Ordinary `sk-gpushare-*` key | Agent API key |
|---|---|---|
| Endpoints | any `/v1/*` (you choose the model) | **only** `POST /v1/chat/completions` |
| Model | set by `model` in the body | locked by the agent (the `model` field is ignored) |
| Persona / knowledge base | none | the agent's system prompt is injected automatically, plus retrieval over attached knowledge bases |
| Who creates it | self-service | issued directly by an org admin; employees request and an admin approves |

---

## Getting an agent API key

Agent API keys are issued from the organization console — they are **not** self-service.

- **Org admins / owners**: console → **[Agent API](https://zhonkezhonkemodel.dflop.top/enterprise/agent-api)** → pick a published organization agent → issue. The plaintext is shown once, and can be viewed again from the list at any time.
- **Org employees**: open an agent in the agent gallery → **"Request an external API key"** → an admin approves and issues it in the console (setting a spend cap at issue time) → find and use it on your own API Keys page.

Issued keys use the same format as ordinary keys (`sk-gpushare-` plus 64 hex characters); for auth see [Authentication](./authentication.md) (`Authorization: Bearer`, `x-api-key` or `?key=`).

> An agent API key is an **org asset**: usage is billed to the organization account and constrained by the org model allowlist, independent of the personal quota of whoever issued it.

---

## Calling it

The endpoint is always `POST https://zhonkezhonkeapi.dflop.top/v1/chat/completions`, and the body is the standard OpenAI Chat Completions shape. **The `model` field is ignored** (the agent has a locked model), so any placeholder works — `"agent"` is the convention.

### curl

```bash
curl https://zhonkezhonkeapi.dflop.top/v1/chat/completions \
  -H "Authorization: Bearer $AGENT_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "agent",
    "messages": [{"role": "user", "content": "What is the expense reimbursement policy?"}]
  }'
```

### Streaming (SSE)

```bash
curl https://zhonkezhonkeapi.dflop.top/v1/chat/completions \
  -H "Authorization: Bearer $AGENT_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"agent","messages":[{"role":"user","content":"Hello"}],"stream":true}'
```

### OpenAI Python SDK

```python
from openai import OpenAI

client = OpenAI(
    api_key="sk-gpushare-...",            # the agent API key
    base_url="https://zhonkezhonkeapi.dflop.top/v1",
)

resp = client.chat.completions.create(
    model="agent",                         # placeholder; the agent locks the model
    messages=[{"role": "user", "content": "What is the expense reimbursement policy?"}],
)
print(resp.choices[0].message.content)
```

Any OpenAI-compatible client (LangChain, n8n, Coze, your own backend…) works by pointing at `https://zhonkezhonkeapi.dflop.top/v1` with this key — no code changes.

---

## What the backend does

Before forwarding upstream, each request goes through:

- **Persona injection**: the agent's system prompt is inserted as the first system message (taking precedence over any system message the client sent).
- **Model locking**: the real model comes from the agent's configuration (`agent.model_id`, falling back to the org default then the platform default). The client's `model` field is ignored.
- **Knowledge retrieval**: if the agent has knowledge bases attached, the backend searches them using your **most recent user message** (scoped to what the agent's creator can see), injects the relevant pages into context, and then answers (single-round RAG).
- **Capability switches**: when the agent has web search or image generation enabled and the chosen model supports it, the matching built-in tool is enabled automatically. **Any `tools` / `functions` the client sends are ignored** — capabilities come from the agent's configuration, and that's a security boundary.
- **Temperature**: the agent's `temperature` applies unless the client sets one explicitly.
- **Multimodal**: OpenAI content arrays (including `image_url`) are supported, but only when the agent's model has vision — otherwise you get a `400`.

### Multi-turn is stateless

v1 keeps **no server-side session storage**. For multi-turn conversations, carry the full context in `messages[]` exactly as you would against OpenAI directly. `conversation_id` isn't supported yet.

> **Caching tip**: for multiple turns in one conversation, send a `session_id` (or `conversation_id`) **request header** — the backend uses it to pin the conversation to a fixed upstream account, hitting the prefix cache and substantially reducing the cost of repeated context. Without it, every turn is recomputed at full price.

---

## Billing

- Billed per token against the **organization account** (the org balance, or the key's funded reserve), at the same rates as ordinary models — see [Models](./models.md).
- Keys requested by employees must have a **spend cap** (a funded reserve); keys an admin issues directly may have no cap and draw on the org balance.
- Usage is aggregated per agent, and admins can see each agent's external API consumption in the console.
- **At-least-once**: a client retry after a network interruption bills twice, so deduplicate on the client side.

---

## Error codes

The error body matches every other endpoint (see [Error codes](./errors.md)): `{"error": {...}}` in the OpenAI shape.

| HTTP | Meaning | What to do |
|---|---|---|
| `401` | Key invalid, revoked, expired, or the account is disabled | Check the key; revocation is irreversible, so a new key must be issued |
| `402` | Org balance insufficient, or the key hit its spend cap | Top up the org account or raise the key's cap |
| `403` | The agent is unavailable (deleted, unpublished, or belongs to another org), the model isn't in the org allowlist, or an attached knowledge base is inaccessible | Confirm the agent is still published, the model is authorised, and the knowledge base is valid |
| `400` | Malformed body, or an image was sent to a model without vision (`model_no_vision`) | Fix the request |

**Scope restriction (fail-closed)**: an agent API key can call **only** `POST /v1/chat/completions`. Requests to `/v1/messages`, `/v1/responses`, `/v1beta/...`, `/v1/images`, `/v1/videos`, `/v1/embeddings`, the knowledge-base REST/MCP endpoints or anything else are rejected — it never degrades into an unrestricted org key.

---

## Lifecycle and security

- **Valid until revoked**: keys don't expire by default and keep working until an admin **revokes or deletes** them in the console (revocation takes effect immediately).
- **Plaintext viewable any time**: admins can re-reveal any agent key in their organization, and employees can re-reveal their own, from the console (stored encrypted server-side). Every view is audited.
- **A note on knowledge-base exposure**: callers of an external API may be anonymous, and in principle they can coax an agent into repeating the content of an attached knowledge base. Attaching a knowledge base means accepting that its content is reachable through the agent's responses — for sensitive bases, state the constraints in the agent's persona, or don't attach them to a publicly exposed agent.
- **Auditing**: issuing, approving, revoking and revealing plaintext are all recorded append-only and visible to admins.
