# Integrate an existing service

Adapt an existing application to receive signed deliveries and return asynchronous Anywe replies.

Source: https://anywe.dev/docs/guides/existing-service-integration

Keep your application's logic and add one narrow adapter at its edge that speaks the signed Anywe delivery and reply contract. The platform calls your agent; your agent never calls the platform as though it were an outbound API client.

**The boundary:** Receive (raw body) -> Verify (exact bytes) -> Dedupe (X-Delivery-Id) -> Acknowledge (2xx, fast) -> Work (off request) -> Reply (POST /reply)

**Before you start**

- Your own service, already working, with logic you are not rewriting.
- An HTTPS endpoint the platform can reach, or `anywe listen --relay` for local development (see [prove the loop](/docs/guides/quickstart#prove-the-loop)).

## Adapt the boundary

The [API overview](/docs/api/overview) defines the agent-facing hook surface. The [interaction reference](/docs/interactions/reference) defines the reply block vocabulary; use it instead of inventing a private rendering format.

This is the shape `anywe init` generates for you, condensed to the boundary:

```go
func (a *agentServer) handleDelivery(w http.ResponseWriter, r *http.Request) {
	rawBody, _ := io.ReadAll(http.MaxBytesReader(w, r.Body, maxBodyBytes))
	if err := verifySignature(a.config.Secrets, r.Header.Get("X-Platform-Signature"), rawBody, time.Now()); err != nil {
		http.Error(w, `{"error":"invalid signature"}`, http.StatusUnauthorized)
		return
	}

	deliveryID := r.Header.Get("X-Delivery-Id")
	if a.alreadyHandled(deliveryID) {
		writeAccepted(w) // a retry of work already accepted, acked not repeated
		return
	}
	writeAccepted(w) // ack first: everything below runs after the platform was told "received"

	go a.answerAndReply(rawBody, deliveryID) // off the request goroutine
}

func (a *agentServer) answerAndReply(rawBody []byte, deliveryID string) {
	blocks, err := a.answer(rawBody) // your service's logic
	if err != nil {
		return
	}
	body, _ := json.Marshal(reply{Version: "1", InReplyToDeliveryID: deliveryID, Blocks: blocks})
	req, _ := http.NewRequest(http.MethodPost, a.config.APIBaseURL+"/hooks/v1/reply", bytes.NewReader(body))
	req.Header.Set("X-Platform-Signature", signRequest(a.config.Secrets[0], time.Now(), body))
	req.Header.Set("Authorization", authorizationValue(a.config.AgentID, a.config.CredentialID))
	req.Header.Set("Idempotency-Key", deliveryID) // the delivery id doubles as the key
	_, _ = http.DefaultClient.Do(req)
}
```

`verifySignature`, `signRequest`, and `authorizationValue` are not invented here: they are the generated `signature.go`'s own functions, and `writeAccepted`/`alreadyHandled` are `main.go`'s. You read them; you do not usually need to change them.

**Receive and verify**

Read a bounded raw request body, verify `X-Platform-Signature` over those exact bytes, then inspect the authenticated `X-Delivery-Id`. Store that ID as the incoming deduplication key before parsing the envelope or handing it to your service.

**Acknowledge promptly**

Return a 2xx response before doing anything slow. It says the delivery was accepted, not that your service has finished; synchronous model calls, remote tools, or long database work belong after it.

**Reply asynchronously**

Build a reply whose `in_reply_to_delivery_id` is the received delivery ID, sign the final bytes, and `POST /hooks/v1/reply` with `Idempotency-Key` set to that same delivery ID across retries. See [one-shot replies](/docs/guides/reply-workflows#one-shot-replies) for the complete payload.

## When something does not work

> **Do not reserialize before verification** Changing JSON spacing or key order changes the bytes the HMAC protects. Verify the received raw bytes first, and preserve the exact outbound bytes when signing a reply.

A `202` from your adapter is acceptance, not evidence that a client rendered anything. If verification keeps failing, check the exact header grammar in [request signing](/docs/api/security-signing).

## Next steps

- **Send the reply.** [Reply workflows](/docs/guides/reply-workflows) covers one-shot, streaming, and asset replies in full.
- **Add a mediated action.** [Request an approved action](/docs/guides/approvals) covers a tool call a person must approve.
- **Read the security contract.** [Request signing](/docs/api/security-signing) and [permissions and approvals](/docs/api/security-permissions-and-approvals) define the boundary this adapter must obey.
