> ## 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.

`StructuredPromptRequestMaterializer` is the default and only bundled materializer. It
uses prompt classes and bundled Twig markdown templates. Custom prompt classes are the
supported extension seam.

## 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="1d84"
```

### 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="c678"
```

### 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="0c6f"
```

### 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="82b7"
```

## 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="d999"
```

## 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="ee0f"
```

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.

Cached prompt content is not 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.

## Replacing The Materializer

When prompt-class customization is not enough, implement `CanMaterializeRequest` and
inject it into the runtime:

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

$runtime = StructuredOutputRuntime::fromDefaults()
    ->withRequestMaterializer($customMaterializer); // your CanMaterializeRequest

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

## 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="d4bf"
```

The generic `Template` package supports Twig, Blade, and Arrowpipe. That does not make
the bundled Instructor prompts engine-selectable: the bundled prompt set uses Twig.
Render alternate templates before passing them to `StructuredOutput`, or supply custom
prompt classes. See the Template package documentation for full details.
