---
title: "Run Echo Upstream"
url: "https://docs.caracal.run/v1.0/examples/echo-upstream/"
markdown_url: "https://docs.caracal.run/markdown/v1.0/examples/echo-upstream.md"
description: "Start the local protected target that proves Gateway-brokered requests reach an upstream service."
page_type: "workflow"
concepts: []
requires: []
---

# Run Echo Upstream

Canonical URL: https://docs.caracal.run/v1.0/examples/echo-upstream/
Markdown URL: https://docs.caracal.run/markdown/v1.0/examples/echo-upstream.md
Description: Start the local protected target that proves Gateway-brokered requests reach an upstream service.
Page type: workflow
Concepts: none
Requires: none

---

Echo Upstream is a zero-dependency HTTP service in the [Caracal examples repository](https://github.com/Garudex-Labs/examples) under `echoUpstream/`. It stands in for the API you would put behind Caracal, so you can verify a Gateway-mediated request end to end without hosting your own upstream. Every response states whether the call was brokered by the Gateway or hit the service directly, and shows the evidence behind that verdict.

## When to use it

Use it as a disposable resource server while validating Gateway routing, provider injection, headers, and audit. It does not verify Caracal mandates itself and is not a production authorization boundary.

## Prerequisites

* A ready Caracal runtime and Docker network access from Gateway.
* A `resource://pipernet` resource, provider, operations, active policy, and scoped caller mandate.

## What it demonstrates

| Area | Behavior |
| --- | --- |
| Brokered-call proof | Reports `viaGateway` plus the request ID, trace context, and forwarding metadata the Gateway stamped on the request. |
| Credential handling | Confirms the Gateway injected the brokered credential and redacts credential values from the echoed headers. |
| Gateway reachability | Joins the `caracalData` Docker network so Gateway can reach `http://echoUpstream:8088`. |
| Local debugging | Exposes `http://127.0.0.1:8088` on the host and logs one line per request, marked `[gateway]` or `[direct]`. |

## Run with Docker

```bash
git clone https://github.com/Garudex-Labs/examples.git caracal-examples
cd caracal-examples/echoUpstream
docker compose -f compose.yml up --build
```

Check the local health endpoint:

```bash
curl http://127.0.0.1:8088/healthz
```

## Run with Node

```bash
cd caracal-examples/echoUpstream
npm start
```

The server listens on port `8088`. Set `ECHO_PORT` when you need a different local port.

## Use as the protected upstream

In web console guided setup or through the Control API, create a resource with this upstream URL:

```text
http://echoUpstream:8088
```

Then send a request through the Gateway with the SDK transport from [First Protected Call](/v1.0/get-started/first-protected-call/#the-agents-first-protected-call), pointing it at this resource. With the application identity from guided setup in the environment, the call has this shape:

```typescript
import { Caracal } from '@caracalai/sdk'

const caracal = new Caracal()
const governedFetch = caracal.applicationTransport('resource://pipernet', {
  scopes: ['pipernet:read'],
})
const target = caracal.gatewayRequest('resource://pipernet', '/v1/hello')
const response = await governedFetch(target.url)
console.log(await response.text())
await caracal.close()
```

## Read the response

A brokered call returns `"viaGateway": true` with a `gateway` section:

| Field | What it proves |
| --- | --- |
| `viaGateway` | The request carried the Gateway's request ID and forwarding metadata. |
| `gateway.requestId` | Audit handle - filter web console **Audit** by it to trace the policy decision. |
| `gateway.credentialInjected` | The Gateway brokered a credential the client never held. |
| `request.headers` | The headers the upstream actually received, with credentials redacted. |

Calling `http://127.0.0.1:8088/` directly returns `"viaGateway": false`, which makes the difference between a protected and an unprotected path visible.

## Test

```bash
cd caracal-examples/echoUpstream
npm test
```

Expected result: direct traffic reports `viaGateway: false`; the Gateway path reports `viaGateway: true`, redacts credentials, and provides a request ID that resolves to STS and Gateway evidence.

:::caution[Failure point: direct port]
Host port `8088` deliberately bypasses Gateway. Never interpret a successful direct curl as proof of authorization, and do not expose an equivalent bypass in production.
:::

## Next Step

Continue to [Bootstrap Control State](/v1.0/examples/control-bootstrap/) when you want repeatable setup for demo resources and policies.
