> ## Documentation Index
> Fetch the complete documentation index at: https://docs.instructorphp.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Prompts

Instructor provides several prompt hooks that let you shape the messages sent to the LLM. These are intentionally simple -- Instructor is not a prompt management framework, but it gives you the building blocks you need for most structured output tasks.

During the current rollout there are two materialization paths:

* `RequestMaterializer` is the legacy/default implementation
* `StructuredPromptRequestMaterializer` is the new implementation built on prompt classes and markdown templates

You can switch between them via `StructuredOutputRuntime::withRequestMaterializer()` without changing the caller-facing `StructuredOutput` code.

## Prompt Hooks

### System Message

Set a system-level instruction that frames the entire extraction task.

```php theme={null}
use Cognesy\Instructor\StructuredOutput;

$result = (new StructuredOutput)
    ->withSystem('You are a data extraction assistant. Be precise and thorough.')
    ->with(messages: $text, responseModel: Person::class)
    ->get();
// @doctest id="7e26"
```

### User Prompt

Add an additional prompt that supplements the input messages. This is useful for providing extraction instructions without mixing them into the data.

```php theme={null}
$result = (new StructuredOutput)
    ->withPrompt('Extract all person information. If age is not stated, estimate based on context.')
    ->with(messages: $text, responseModel: Person::class)
    ->get();
// @doctest id="2b72"
```

### Examples

Provide input/output examples to guide the LLM's extraction behavior. Few-shot examples are one of the most effective ways to improve extraction accuracy.

```php theme={null}
use Cognesy\Instructor\Extras\Example\Example;

$result = (new StructuredOutput)
    ->withExamples([
        new Example(
            input: 'Dr. Smith is a 45-year-old cardiologist from Boston.',
            output: ['name' => 'Dr. Smith', 'age' => 45, 'occupation' => 'cardiologist'],
        ),
    ])
    ->with(messages: $text, responseModel: Person::class)
    ->get();
// @doctest id="b370"
```

### Combined Usage

All prompt hooks can be used together in a single request, either through the fluent API or the `with()` shorthand.

```php theme={null}
$result = (new StructuredOutput)
    ->withSystem('You are a precise data extraction assistant.')
    ->withPrompt('Extract person details from the text below.')
    ->withExamples($examples)
    ->withMessages($text)
    ->withResponseClass(Person::class)
    ->get();

// Or equivalently:
$result = (new StructuredOutput)->with(
    system: 'You are a precise data extraction assistant.',
    prompt: 'Extract person details from the text below.',
    examples: $examples,
    messages: $text,
    responseModel: Person::class,
)->get();
// @doctest id="f93a"
```

## Using Stringable Objects as Prompts

Both `withSystem()` and `withPrompt()` accept `string|\Stringable`, so you can pass any object that implements `Stringable` -- such as an xprompt `Prompt` class -- directly, without calling `->render()` or `(string)` yourself. The value is cast to string immediately at the boundary.

```php theme={null}
use Cognesy\Instructor\StructuredOutput;
use App\Prompts\ExtractionSystem;

$result = (new StructuredOutput)
    ->withSystem(ExtractionSystem::with(domain: 'finance'))
    ->withPrompt('Extract person details from the text below.')
    ->with(messages: $text, responseModel: Person::class)
    ->get();
// @doctest id="089c"
```

## Cached Context

For applications that use the same large context across multiple requests (such as a long document or a set of reference materials), `withCachedContext()` marks content for provider-level prompt caching. This can significantly reduce costs and latency when supported by the provider.

```php theme={null}
$result = (new StructuredOutput)
    ->withCachedContext(
        system: 'You are a legal document analyst.',
        messages: $longDocument,
        prompt: 'Extract all party names and obligations.',
        examples: $examples,
    )
    ->with(messages: 'Focus on section 3.', responseModel: ContractDetails::class)
    ->get();
// @doctest id="12e1"
```

Cached context messages are placed before the regular messages in the chat structure. The exact caching behavior depends on the LLM provider -- Anthropic and OpenAI both support prompt caching with different mechanisms.

On the new `StructuredPromptRequestMaterializer` path, cached prompt content is no longer flattened into ordinary live messages. It is projected into `InferenceRequest::cachedContext()` so provider-native caching can take effect, while the per-request prompt remains live.

## Switching Materializers

```php theme={null}
use Cognesy\Instructor\Core\RequestMaterializer;
use Cognesy\Instructor\Core\StructuredPromptRequestMaterializer;
use Cognesy\Instructor\StructuredOutput;
use Cognesy\Instructor\StructuredOutputRuntime;

$runtime = StructuredOutputRuntime::fromDefaults()
    ->withRequestMaterializer(new StructuredPromptRequestMaterializer());

$legacyRuntime = $runtime->withRequestMaterializer(new RequestMaterializer());

$so = (new StructuredOutput)
    ->withRuntime($runtime)
    ->with(messages: $text, responseModel: Person::class);
// @doctest id="3eb7"
```

This lets you run the same requests against both paths while the new materializer is being proven.

## Template Engine Integration

If your application needs a more sophisticated prompt management system with variable interpolation, conditional logic, or template libraries, use the companion `Template` class from the `cognesy/template` package.

```php theme={null}
use Cognesy\Template\Template;

$rendered = Template::twig()
    ->from('Extract {{ entity_type }} from the following text: {{ text }}')
    ->with(['entity_type' => 'person', 'text' => $input])
    ->toText();

$result = (new StructuredOutput)
    ->with(messages: $rendered, responseModel: Person::class)
    ->get();
// @doctest id="ed9e"
```

The `Template` class supports Twig and Blade template engines, front matter metadata, chat message markup, and template libraries loaded from disk. Render your templates into strings or message arrays, then pass the result into `StructuredOutput`. See the Template package documentation for full details.
