Laravel AI can expose the underlying provider response through a nullable raw property. It is a useful escape hatch for diagnostics, rate-limit monitoring and support, provided those provider-specific details stay at the edge of the application.
01
The normal response should remain the normal route
Imagine a Laravel application that uses an AI agent to prepare a review summary for a customer case. The useful result for the business is the summary, perhaps supported by structured fields such as a risk level and a list of missing evidence.
The controller or service should care about that result. It should not normally care whether the model came from OpenAI, Anthropic, Gemini or another provider. That is one of the main reasons to use the Laravel AI SDK instead of spreading direct HTTP calls throughout the application.
A normal prompt can stay pleasantly small. The application uses the generated text or structured result, while the SDK handles the provider-specific request and turns the response into Laravel's common shape.
That common shape is not supposed to contain every header and payload field every provider might ever return. If it tried, the abstraction would soon become a storage cupboard where every provider had left one unusual cable.
02
What the raw response gives you
Laravel AI 0.10.3 added a public raw property to text-generating agent responses. It contains an Illuminate HTTP client Response when the provider call was made through Laravel's HTTP client, so familiar methods such as header(), json() and status() are available.
- Support and diagnosis: record the provider's own request ID so a failed or strange generation can be traced on the provider side.
- Rate-limit awareness: inspect the remaining request or token budget and alert before a busy workflow repeatedly hits a hard limit.
- Provider-specific metadata: read a field that matters to operations but does not belong in the SDK's shared response model.
The exact header names and payload fields vary by provider. Laravel gives you the response object, but it cannot make one provider use another provider's naming scheme.
This is an observability feature more than a content feature. The generated answer should still come from the typed Laravel response. The raw response supplies evidence about the request around it.
03
Keep provider details near the edge
The tempting version reads a provider header in every controller that prompts an agent. It works at first, then the header name appears in jobs, commands, listeners and tests. Changing provider becomes a search-and-replace exercise with a small prayer attached.
A cleaner approach is to translate provider details once. That can happen in a dedicated recorder, middleware layer or AgentPrompted event listener. The listener can capture the provider, model, local invocation ID, provider request ID and HTTP status, while the case review code remains focused on the case review.
For an application supporting several providers, place the header mapping behind a small adapter. The rest of the system can ask for a provider request ID without knowing whether that value came from request-id, another header or the response body.
That boundary also makes testing easier. Most application tests can fake the typed agent response and ignore the transport. A smaller set of observability tests can prove the provider mapping.
04
One agent run can contain several HTTP responses
An agent that uses tools may make several provider requests before it produces the final text.
The provider can ask the application to call a tool. Laravel runs the tool, returns the result to the model and continues the conversation. A run with three tool turns and one final answer is not one provider request. It is a short chain of requests.
The response raw property represents the final request in that chain. Each item in response steps retains its own nullable raw response. This matters when you are investigating cost, latency or rate-limit pressure because the final response alone can hide the work performed during earlier tool steps.
It does not mean every step needs to be dumped into a log file. Decide which operational values answer a real question, extract those values and leave the rest alone.
05
Expect raw to be null
- Streaming responses are assembled from events rather than returned as one completed HTTP response.
- Amazon Bedrock uses the AWS SDK rather than Laravel's HTTP client.
- Faked responses have no raw provider response unless the test supplies one with withRawResponse().
- Serialized responses drop raw because the underlying response stream cannot safely be serialized through a queue or cache.
The property is deliberately nullable. Code that assumes the raw response always exists will eventually fail in one of the places where it cannot be carried forward.
Use the null-safe operator when reading it. More importantly, decide whether the information is essential or optional.
If a provider request ID is useful diagnostic context, a missing value should not break the customer workflow. If a rate-limit value controls whether another job can be dispatched, treat the missing value as an explicit state and use a safer source of truth rather than pretending it is zero or unlimited.
For queued work, extract the small scalar value you need before serialization and pass that value forward. Do not try to preserve the whole HTTP response simply because it is available at the prompt site.
06
Fake the transport detail when it drives behaviour
Most agent tests should remain interested in the application result. If a listener warns when the provider's remaining request budget is low, that transport detail now drives behaviour and deserves a focused test.
Laravel AI lets a fake TextResponse carry an Illuminate HTTP client Response through withRawResponse(). The test can set a rate-limit header and then prove the application records a warning, updates an operational metric or chooses not to dispatch more optional work.
The useful test is not that Laravel's header() method returns a header. Laravel already tests its HTTP client. Your test should prove your application reacts correctly.
Keep the fake close to the boundary it exercises. Requiring every feature test to construct a PSR-7 response would be a sign that provider transport has escaped too far into the application.
07
Raw does not mean log everything
A raw response is easier to access, but that does not make every part of it safe or useful to store.
AI responses may contain generated text, tool-call arguments, identifiers and provider metadata. Depending on the application, those values can relate to customers, employees, commercial records or other sensitive information. Logging the entire body can turn a debugging shortcut into a new data-retention problem.
Prefer an allowlist of specific fields. A local invocation ID, provider name and model, provider request ID, HTTP status, selected rate-limit values and approved timing or usage measures are usually more useful than the whole body.
Do not store prompts, attachments, generated content or tool arguments by default. Redact secrets and apply the same access, retention and deletion rules used for other operational logs.
The raw response is evidence from an external boundary. Treat it with the same care as payment-provider payloads, webhook bodies and third-party API errors.
08
Use the escape hatch without moving into it
Laravel AI's raw HTTP response support fills a sensible gap. A shared SDK response is excellent for application code, but operations occasionally need the exact request ID, rate-limit header or provider field that the common model leaves out.
Use the typed response and structured output for normal business behaviour. Use raw at a narrow observability or integration boundary. Translate the provider-specific detail into a small application-owned record, expect it to be missing and test only the behaviour that depends on it.
For the case review workflow, the generated summary still belongs to the case. The raw response helps the support team understand how that summary was produced and trace a problem when something goes wrong.
That is a useful escape hatch. It gives you more evidence without asking the whole application to move outside the abstraction that made the Laravel AI SDK useful in the first place.
If you are adding AI features to an established Laravel application, I can help design the integration, testing and operational controls so the feature is useful in production as well as impressive in a demo.
Useful questions
Before using a Laravel AI raw response, check:
- Does normal business behaviour still use the typed SDK response?
- Is the raw response read in one listener, recorder or provider adapter?
- Have you checked the exact header or payload field used by the selected provider?
- Does the code safely handle a null raw response?
- Have multi-step tool calls been considered rather than only the final response?
- Are queued jobs passed small scalar values instead of the whole response?
- Does each fake use withRawResponse() only when transport detail drives behaviour?
- Are logs limited to an allowlist of operational fields?
- Are prompts, attachments, generated content and secrets excluded by default?
- Can the provider mapping change without rewriting controllers and business services?


