VanaAPI

← Writing

Notes on a first Messages API integration

Wire formatsEN2026-10-28

The Anthropic Messages API is straightforward to call, but a dependable integration requires more than sending a prompt and reading a string. For developers arriving from another API, the useful starting point is its conversation structure: messages contain typed content blocks, the application maintains history, and a response can request work rather than finish an answer.

These notes focus on the decisions worth making before a small experiment becomes a production dependency.

§ Keep the protocol separate from the provider

The native Anthropic API uses POST /v1/messages. A typical request includes a model identifier, max_tokens, and a messages array. Persistent instructions belong in the top-level system field, not in a message with a system role. Native Anthropic requests also use authentication and an anthropic-version header; check the gateway’s requirements when routing through another service.

Vana API provides one endpoint at https://api.vanaapi.com with OpenAI-compatible, Anthropic Messages, and Gemini native protocols. That lets an application retain the Messages request shape instead of translating everything into an OpenAI-style conversation. Use the documented model identifier rather than deriving one from a display name such as Claude Haiku 4.5.

§ Make content blocks your internal representation

A response’s content field is an array, not a guaranteed string. Text blocks are only one possibility. Tool requests and other supported content types can appear alongside them. Joining text blocks is useful for display, but flattening the entire response loses information needed for the next request.

Store structured messages as the source of truth. Derive a plain-text transcript for logs or interfaces separately. This small architectural choice prevents a later tool integration from requiring a rewrite of conversation storage.

§ Treat history as application state

Ordinary Messages calls are stateless: the service does not reconstruct the conversation from your previous request. Your application sends the relevant history each time. Preserve role ordering and content structure, especially around tool exchanges.

As history grows, introduce an explicit retention policy. Keep recent turns intact, summarize older discussion, and preserve important constraints separately. A summary is a lossy representation, so retain original messages somewhere recoverable when auditability matters. Measure input usage rather than assuming a conversation remains inexpensive because each new user message is short.

§ Read the stop reason before taking action

A successful HTTP response does not necessarily mean the assistant has finished. Inspect stop_reason together with the content blocks.

  • end_turn: the assistant has completed its turn.
  • max_tokens: the output reached its configured limit; do not assume the result is complete.
  • tool_use: the application must handle the requested tool operation before the conversation can proceed.

Keep these branches explicit. Otherwise, a truncated answer can be displayed as complete, or a tool request can disappear into a generic text renderer.

§ Run tools behind an application boundary

A tool definition describes an available operation and its input schema. It does not execute anything. When the assistant returns a tool_use block, validate its input, apply authorization checks, execute the operation, and return a tool_result block in a subsequent user message. Match tool_use_id to the original tool request’s identifier.

If several tool requests arrive together, return the corresponding results before continuing the assistant’s turn. Treat tool arguments as untrusted input. For payments, writes, or external messages, use confirmation and idempotency controls rather than assuming a retry is harmless.

§ Stream events, not assumptions

Streaming improves perceived responsiveness, but an event is not necessarily a complete word, JSON object, or content block. Accumulate deltas by block index, and wait for complete tool input before parsing or executing it. Handle stream errors and disconnections explicitly; receiving some text is not proof that the response completed.

Record latency, stop reason, and available usage fields. Retry transient failures with bounded backoff, while preventing repeated tool side effects. Set max_tokens for the expected task instead of using a large default everywhere.

§ Start with one observable workflow

Vana API bills per actual token with no monthly fee. Create an account, then test one short conversation, one truncated response, and one tool exchange. A small integration with visible state transitions is easier to trust than a broad abstraction that hides them.