HTTP client
The standard library of AEL, the Agent Engineering Language, includes a client for HTTP and HTTPS, so a program can call web APIs with no package to add. Calling out never makes a program a server: the client opens no listening port, and a console agent that calls APIs stays a console agent.
# pack.ael: calling web APIs needs no package
pack {
schema = 1;
dependencies = [];
}
To accept requests instead, you add the optional server/http package and declare routes; see Services and APIs.
What a request is
- Typed. A request carries a method, an address, headers and a body; a response carries a status, headers and a body. Both are values your code builds and reads like any other.
- Bounded. Request and response bodies have a maximum size. A response larger than its limit is reported as an error, never cut off silently.
- Streamed when you ask. A response is readable as a stream, with backpressure: the client reads more only when your code is ready for it.
- Deadline-bound. Every request has a finite deadline, inherited from the work that makes it, and is cancellable.
Many requests, few threads
The client is nonblocking. A multi-core, nonblocking runtime needs no thread per user: while one request waits for the network, other work runs, and many requests are in flight at once without a thread each. Connections to the same service are reused from a pool with a fixed limit. Programs that don't need worker threads don't get them.
Security
- HTTPS connections are authenticated with TLS.
- Endpoints and credentials come from configuration, not from your source. A credential is passed by reference, so it stays out of your source, your manifest, your logs and command-line arguments.
- Opening a network connection is an effect, and reaching a destination a permission your program grants. See Effects and capabilities.
- A response is data. Nothing in it can grant your program a permission or choose where a reply goes.
Retries and resilience
Connections are resilient, with idempotency-aware retries, backpressure, circuit breakers and health checks.
- A request is retried only when it is safe to repeat: a read, or a write that carries an idempotency key, which marks every attempt as the same change.
- Retries wait with a growing, slightly randomized delay, and honour a server's request to wait, but never past the deadline.
- Every attempt and every wait draws on the budget of the work that made the request, so a retry cannot multiply its cost.
- A write that times out is never repeated blindly. Its effect is reported as uncertain, for your code to reconcile.
- The client makes no hidden retries of its own.
- A service that keeps failing trips a circuit breaker, so new requests fail at once instead of piling up; the breaker closes again when the service recovers.
Failures
A failed request returns a typed error, so your code can react to each case. The kinds of failure include:
| Failure | Meaning |
|---|---|
| Connection | The service could not be reached. |
| TLS | The service's identity could not be verified. |
| Timeout | The deadline passed before the response arrived. |
| Cancelled | The work that made the request was cancelled. |
| Too large | A body passed its size limit. |
| Circuit open | The service has been failing, and the request was not sent. |
| Uncertain | The request may have reached the service; its effect is unknown. |
Calling your own services
Code calls a typed service, and the deployment decides whether it runs in the same process, on another machine, over HTTPS or over gRPC. Your code stays the same when the service moves. See Tools and MCP.
Models and tools
The Model client and the MCP client (Tools and MCP) use this client to reach their endpoints, with the same deadlines, budgets and credentials rules.
Where it runs
- Desktop, server and containers: the full client.
- Small networked boards: HTTPS where the board's profile provides networking and TLS. Microcontroller boards lists the boards and their profiles.
- The smallest boards: no network of their own. They reach services through AEL Gateway.