Skip to content

Conversation

s-akhtar-baig
Copy link
Contributor

@s-akhtar-baig s-akhtar-baig commented Oct 8, 2025

Problem

The current inline provider appends the user provided instructions to messages as a system prompt, but the returned response object does not contain the instructions field (as specified in the OpenAI responses spec).

What does this PR do?

This pull request adds the instruction field to the response object definition and updates the inline provider. It also ensures that instructions from previous response is not carried over to the next response (as specified in the openAI spec).

Closes #3566

Test Plan

  • Tested manually for change in model response w.r.t supplied instructions field.
  • Added unit test to check that the instructions from previous response is not carried over to the next response.
  • Added integration tests to check instructions parameter in the returned response object.
  • Added new recordings for the integration tests.

Copy link

meta-cla bot commented Oct 8, 2025

Hi @s-akhtar-baig!

Thank you for your pull request.

We require contributors to sign our Contributor License Agreement, and yours needs attention.

You currently have a record in our system, but the CLA is no longer valid, and will need to be resubmitted.

Process

In order for us to review and merge your suggested changes, please sign at https://code.facebook.com/cla. If you are contributing on behalf of someone else (eg your employer), the individual CLA may not be sufficient and your employer may need to sign the corporate CLA.

Once the CLA is signed, our tooling will perform checks and validations. Afterwards, the pull request will be tagged with CLA signed. The tagging process may take up to 1 hour after signing. Please give it that time before contacting us about it.

If you have received this in error or have any questions, please contact us at [email protected]. Thanks!

@s-akhtar-baig s-akhtar-baig changed the title Add support for instructions parameter in response object feat: Add support for instructions parameter in response object Oct 8, 2025
Copy link

meta-cla bot commented Oct 8, 2025

Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Meta Open Source project. Thanks!

@meta-cla meta-cla bot added the CLA Signed This label is managed by the Meta Open Source bot. label Oct 8, 2025
@s-akhtar-baig s-akhtar-baig changed the title feat: Add support for instructions parameter in response object feat: Add instructions parameter in response object Oct 8, 2025
"type": "string",
"description": "(Optional) Truncation strategy applied to the response"
},
"instructions": {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

openai's docs say this can be a string or an array

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, @ashwinb, for reviewing! I have updated the definition using openai/types/responses as my reference. Please take a look when you get a chance.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting that this shows a String only but the Python client is definitely the source of truth!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, I tried this with the Python client talking directly to OpenAI (not Llama Stack):

r3 = open_ai_client.responses.create(
    model="gpt-4o",
    input="What is the capital of France?",
    instructions=["Always answer with rhyming poetry.", "Include the word 'cat' in your answer."]
)

What I got was:

BadRequestError: Error code: 400 - {'error': {'message': "Invalid type for 'instructions': expected a string, but got an array instead.", 'type': 'invalid_request_error', 'param': 'instructions', 'code': 'invalid_type'}}

So the OpenAI client does indeed accept the list and send it off to the server but then the server rejected it because the server API expects a string only. So I guess the API reference that @leseb links to above is correct.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jwm4, that makes sense! The link that @leseb shared brings me to the create endpoint which accepts string, but the response object can store instructions as a string or an array.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So is the conclusion that this PR is fine the way it is? (i.e., that Llama Stack should really just accept a string and not a list for instructions)

Copy link
Contributor Author

@s-akhtar-baig s-akhtar-baig Oct 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With these changes, we will be conforming to the OpenAI spec:

  • create response accepts instructions as a string
  • response object can store either a string or an array
  • instructions from previous response is not carried over

But, I am not sure whether that's what we want in Llama Stack or not. If we change create response to accept both a string and an array, then we won't be conforming to the spec and we don't have use-cases (that I can think of) to correctly implement logic that will handle array data type.

Copy link
Collaborator

@franciscojavierarceo franciscojavierarceo Oct 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In [7]: from openai import OpenAI; client = OpenAI()

In [8]: openai.__version__
Out[8]: '1.107.0'

In [9]: client.responses.create.__annotations__
Out[9]:
{'background': 'Optional[bool] | NotGiven',
 'conversation': 'Optional[response_create_params.Conversation] | NotGiven',
 'include': 'Optional[List[ResponseIncludable]] | NotGiven',
 'input': 'Union[str, ResponseInputParam] | NotGiven',
 'instructions': 'Optional[str] | NotGiven',
 'max_output_tokens': 'Optional[int] | NotGiven',
 'max_tool_calls': 'Optional[int] | NotGiven',
 'metadata': 'Optional[Metadata] | NotGiven',
 'model': 'ResponsesModel | NotGiven',
 'parallel_tool_calls': 'Optional[bool] | NotGiven',
 'previous_response_id': 'Optional[str] | NotGiven',
 'prompt': 'Optional[ResponsePromptParam] | NotGiven',
 'prompt_cache_key': 'str | NotGiven',
 'reasoning': 'Optional[Reasoning] | NotGiven',
 'safety_identifier': 'str | NotGiven',
 'service_tier': "Optional[Literal['auto', 'default', 'flex', 'scale', 'priority']] | NotGiven",
 'store': 'Optional[bool] | NotGiven',
 'stream': 'Optional[Literal[False]] | Literal[True] | NotGiven',
 'stream_options': 'Optional[response_create_params.StreamOptions] | NotGiven',
 'temperature': 'Optional[float] | NotGiven',
 'text': 'ResponseTextConfigParam | NotGiven',
 'tool_choice': 'response_create_params.ToolChoice | NotGiven',
 'tools': 'Iterable[ToolParam] | NotGiven',
 'top_logprobs': 'Optional[int] | NotGiven',
 'top_p': 'Optional[float] | NotGiven',
 'truncation': "Optional[Literal['auto', 'disabled']] | NotGiven",
 'user': 'str | NotGiven',
 'extra_headers': 'Headers | None',
 'extra_query': 'Query | None',
 'extra_body': 'Body | None',
 'timeout': 'float | httpx.Timeout | None | NotGiven',
 'return': 'Response | Stream[ResponseStreamEvent]'}

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah looks like the client (as mentioned by @s-akhtar-baig) only lists instructions as a str

@s-akhtar-baig s-akhtar-baig force-pushed the add_instructions_parameter branch from 5f503d6 to 2ce56ab Compare October 13, 2025 19:00
# Omit instructions from previous response
previous_instructions = previous_response.instructions
if previous_instructions:
assert isinstance(previous_instructions, str)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ashwinb and @leseb, I'd appreciate your thoughts on this:

This condition will ensure that instructions is handled and stored as a string for the time being. Because the spec for create response specifies instructions as a string, and I am not sure what the use case would be for storing instructions as an array. Please let me know if I am missing anything.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My take on this is that if the spec say str | list, we should also update the create response.

Copy link
Contributor Author

@s-akhtar-baig s-akhtar-baig Oct 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, @leseb, for reviewing! I have handled other comments and added tests and recordings. Please take a look when you get a chance.

My take on this is that if the spec say str | list, we should also update the create response.

This makes sense! But the thing that comes to mind is that without use cases for other types, I am not sure if we can handle those types correctly, for the time being.

# Omit instructions from previous response
previous_instructions = previous_response.instructions
if previous_instructions:
assert isinstance(previous_instructions, str)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My take on this is that if the spec say str | list, we should also update the create response.

@s-akhtar-baig s-akhtar-baig force-pushed the add_instructions_parameter branch 2 times, most recently from 125aa75 to 3487d0a Compare October 14, 2025 21:39
Copy link
Contributor

@jwm4 jwm4 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic here looks correct to me.

@s-akhtar-baig s-akhtar-baig force-pushed the add_instructions_parameter branch 2 times, most recently from 5dc97a0 to a615f7b Compare October 16, 2025 21:44
@s-akhtar-baig
Copy link
Contributor Author

@ashwinb and @leseb, I have handled your comments and all the checks are passing now. Can you please review when you get a chance? Thanks!

tools: list[OpenAIResponseTool] | None = None
truncation: str | None = None
usage: OpenAIResponseUsage | None = None
instructions: str | list[OpenAIResponseInput] | None = None
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

based on all the discussion so far, I think we should just do what you did first @s-akhtar-baig -- which is that this is just a simple str, that's it. this specific type is not good -- you really are not going to accept arbitrarily complex input as instructions here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, @ashwinb!

The tests have passed, can you please merge when you get a chance? Thanks again!

@s-akhtar-baig s-akhtar-baig force-pushed the add_instructions_parameter branch from a615f7b to f7b6d7f Compare October 20, 2025 19:39
@ashwinb ashwinb merged commit add64e8 into llamastack:main Oct 20, 2025
24 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Meta Open Source bot.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants