# Reach a service before debugging the agent

An agent can choose the right tool and still fail to reach it. Before changing
the prompt, understand how a request gets from one program to another.
This original 40-minute exercise starts with an ordinary local service.
It needs no AI model, cloud account or customer data.

You will run real TCP, TLS and HTTP exchanges on your own computer and explain
why a connection failure, a certificate rejection and an HTTP refusal need
different repairs.

## 1. Understand the four boundaries

Imagine calling a function in another process. You need to find the process,
open a connection, establish the expected peer, and agree on a request format.
Unlike an ordinary in-process function call, any of those steps can fail
independently. A network timeout may also leave a remote action's outcome
unknown; it is not a general invitation to repeat a business write.

| Piece | Plain-language job | What it does not establish |
| --- | --- | --- |
| Hostname and name lookup | Turn a service name into an IP address | That a service is listening there |
| IP address and port | Identify a destination and an endpoint on it | That the endpoint is the expected service |
| TCP | Establish an ordered byte stream between endpoints | Encryption or application permission |
| TLS | Negotiate an encrypted channel; our client also checks the certificate chain and hostname | Permission to read a ticket |
| HTTP | Carry an operation and return a status, headers and body | That every response means the requested task succeeded |

For this exercise, follow:

```text
localhost → 127.0.0.1 → temporary TCP port → verified TLS → GET /ticket
                                                          ↓
                                                HTTP 200 + JSON body
```

**DNS** means Domain Name System: a distributed system used to resolve names.
The operating system may instead answer a lookup from a local hosts file or
cache. Our fixed `localhost` lookup is local; it does not capture or prove an
external DNS exchange. **Loopback** means traffic that returns to this same
machine. Our server binds only to `127.0.0.1`.

This lab uses HTTP/1.1 over TCP and TLS. HTTP/3 uses QUIC instead of this TCP
path. It is a first connection model, not a diagram of every internet protocol.

## 2. Run a private local connection

Download both files into a new folder:

- [Python connection exercise](/templates/fde-first-connection.py)
- [Pinned cryptography requirement](/templates/fde-first-connection-requirements.txt)

Use Python 3.12. In Bash or zsh on macOS/Linux:

```shell
python3.12 -m venv .venv
.venv/bin/python -m pip install -r fde-first-connection-requirements.txt
.venv/bin/python fde-first-connection.py test
.venv/bin/python fde-first-connection.py demo
```

In Windows PowerShell, with Python 3.12 installed:

```powershell
py -3.12 -m venv .venv
.\.venv\Scripts\python.exe -m pip install -r fde-first-connection-requirements.txt
.\.venv\Scripts\python.exe fde-first-connection.py test
.\.venv\Scripts\python.exe fde-first-connection.py demo
```

Package installation requires internet access. The exercise itself connects
only to fixed loopback endpoints. It accepts no arbitrary URL, makes no model
call, and uses no account credentials. Seven checks cover the observed
boundaries, the absence of HTTP requests after TLS failures, and local cleanup.

The program creates an ephemeral certificate authority and a server
certificate for `localhost`. A certificate authority (CA) signs certificates;
the client must decide which authorities it trusts. Here the CA is trusted
only inside the exercise's client context, for one run. Nothing is installed
into your operating system or browser trust store.

The generated server private key exists briefly in an owned temporary folder.
On POSIX systems it is created with owner-only file permissions. The folder is
removed after the case. Do not copy keys into your notes or reuse these
certificates. This is a teaching fixture, not a production certificate service.

If local policy prevents opening a loopback listener, keep that setup failure
as a failure and ask the environment owner for an appropriate local workspace.
Do not open public ports or disable endpoint protections to make the lab pass.

## 3. Predict the first stopping point

Before reading the output, write one prediction per case: does it stop at TCP,
stop at TLS, or receive an HTTP response?

| Case | Controlled change | What to look for |
| --- | --- | --- |
| `success` | Trust the local CA, expect `localhost`, request `/ticket` | A verified TLS version, 200 and one HTTP handler entry |
| `no-listener` | Reserve a local port without starting a listener | TCP refusal or timeout; TLS and HTTP not attempted |
| `wrong-name` | Expect `wrong.localhost` on the same local connection | Certificate name rejection; zero HTTP handler entries |
| `untrusted` | Do not load the temporary CA into this client | Certificate chain rejection; zero HTTP handler entries |
| `denied` | Keep the working connection, request `/restricted` | Verified TLS and a 403 response |

The wrong-name case never resolves or contacts `wrong.localhost`. That string
is the expected TLS peer name; the socket still connects to the fixed local
address. Separating the destination from the expected identity makes the
mismatch visible.

Inspect one case at a time:

```shell
.venv/bin/python fde-first-connection.py inspect --case wrong-name
.venv/bin/python fde-first-connection.py inspect --case untrusted
.venv/bin/python fde-first-connection.py inspect --case denied
```

Use `.\.venv\Scripts\python.exe` instead on Windows. Read the `stages`,
`http_status`, `error` and `http_requests` fields together. A stage marked
`not-run` did not succeed; it was never attempted.

## 4. Separate the connection from permission

In `denied`, name lookup, TCP, TLS and the HTTP exchange all complete.
The application sends 403. The network has delivered a refusal successfully.
Changing DNS or accepting untrusted certificates will not make the resource
authorized.

The fixture's rule is deliberately simple: `/restricted` always returns 403.
It has no users, access tokens, tenant boundaries or policy engine. A real
service needs those controls and tests; a private endpoint does not supply
them automatically. The lesson is that an HTTP refusal is different from
never receiving an HTTP response.

In the two TLS cases, the client rejects the certificate before sending an
HTTP request. Look for `http_requests: 0`, not just an exception message.
The exact verification code and diagnostic depend on the runtime. Keep the
category and the stopped stage beside the original observed message.

Do not “fix” a certificate failure by disabling verification. Check the
intended service name, the certificate names and the approved issuer instead.
Our client requires both a trusted chain and the expected hostname.

## 5. Make one change and explain it

Keep the original script for its reference tests. In a separate disposable
copy, change the successful response body from `service reached` to
`training service reached`. Run the successful case.

The response body changes while lookup, TCP and TLS stay the same. Now explain
which component would need to change if a real client required a different
resource path, a different port or a different service hostname.

Write a small evidence note:

```text
Intended operation:
Case and command:
Runtime versions:
First stopped stage, or HTTP response:
Observed status / error:
Did the HTTP handler run?
Next check supported by this evidence:
What this run did not test:
```

The `demo` output includes actual runtime versions. It omits random port
numbers and temporary certificate paths so the teaching cases can be compared.
It is an application observation, not a packet capture or a latency benchmark.

## 6. Carry the method into a private deployment

For a deployed agent worker, sketch its outbound path to each model, tool and
data service. **Egress** is outbound traffic. A route determines where packets
go; firewalls and security rules may allow or reject them. A proxy or gateway
can introduce another connection and another policy decision.

Ask the platform owner which DNS zone, network route, endpoint, expected TLS
name, trust configuration and application identity the worker should use.
Then test from the worker's actual execution environment. A successful call
from your laptop does not prove that the worker has the same route or policy.

This loopback lab does not test cloud DNS, routing, proxies, firewalls, client
certificate authentication, certificate renewal or revocation, or production
authorization. It gives you a way to locate the next question without
conflating network failure with model behavior.

Return to [Networking 101](/training/fde-101?topic=networking#concept) to place
these pieces in the wider FDE map. With training access, continue into
[deployment and worker operations](/app/academy?course=agent-engineering&lesson=deployment-operations&view=focus).

## 7. Read the primary references

- [Python 3.12: socket connections and name lookup](https://docs.python.org/3.12/library/socket.html)
- [Python 3.12: TLS client contexts and certificate verification](https://docs.python.org/3.12/library/ssl.html)
- [Cryptography: X.509 certificate tutorial](https://cryptography.io/en/stable/x509/tutorial/)
- [IETF: HTTP semantics and response statuses](https://www.rfc-editor.org/rfc/rfc9110.html)

References checked on 20 October 2026. The explanation, fixture and exercise
are original LockedIn Labs training material. Provider courseware is not
included.
