Skip to content

feat(interactions): add previous_interaction_id for multi-turn conversations#5669

Merged
leseb merged 10 commits into
ogx-ai:mainfrom
leseb:leseb/rhaistrat-1348-v4
May 12, 2026
Merged

feat(interactions): add previous_interaction_id for multi-turn conversations#5669
leseb merged 10 commits into
ogx-ai:mainfrom
leseb:leseb/rhaistrat-1348-v4

Conversation

@leseb

@leseb leseb commented Apr 30, 2026

Copy link
Copy Markdown
Member

What does this PR do?

Adds previous_interaction_id support to the Google Interactions API, enabling server-side conversation state for multi-turn interactions. Without this, every request starts fresh and ADK agents cannot maintain context across turns.

When a request includes previous_interaction_id, the server fetches the stored conversation history from the SQL backend, prepends it (including the model's prior response) to the new input, and calls inference with the full context. Both streaming and non-streaming responses are persisted for future chaining.

Key additions:

  • InteractionsStore class (src/ogx/providers/utils/interactions/) following the ResponsesStore pattern with AuthorizedSqlStore and access control policy
  • InteractionsConfig with SqlStoreReference for configurable SQL backend (SQLite/Postgres)
  • _build_messages() method for conversation history reconstruction, supporting multi-hop chaining
  • Updated Google Interactions API conformance score (39.0% → 40.2%)

Test Plan

55 unit tests pass (37 existing + 5 new previous_interaction_id + 13 shape/passthrough tests). All 39 pre-commit hooks pass.

# Unit tests
uv run pytest tests/unit/providers/inline/interactions/ -x --tb=short -q

# End-to-end validation with Google GenAI SDK
OLLAMA_URL=http://localhost:11434/v1 uv run --extra starter ogx stack run starter --port 8321
uv run scripts/test_interactions_api.py --base-url http://localhost:8321 --model ollama/llama3.2:3b

Test 5 validates conversation chaining: creates a first interaction establishing context ("My name is Alice"), then chains from it with previous_interaction_id and verifies the model remembers the name.

…sations

Add server-side conversation state to the Google Interactions API so that
ADK agents can chain requests via previous_interaction_id. Without this,
every request starts fresh and there is no way to maintain context across
turns.

The implementation introduces an InteractionsStore (SQL-backed via
AuthorizedSqlStore, following the ResponsesStore pattern) that persists
each completed interaction. When a request includes
previous_interaction_id, the stored conversation history is fetched and
prepended to the new input before calling the inference API.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Sébastien Han <seb@redhat.com>
@mergify

mergify Bot commented Apr 30, 2026

Copy link
Copy Markdown
Contributor

This pull request has merge conflicts that must be resolved before it can be merged. @leseb please rebase it. https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork

@mergify mergify Bot added the needs-rebase label Apr 30, 2026
@leseb leseb marked this pull request as draft April 30, 2026 14:09
…8-v4

Signed-off-by: Sébastien Han <seb@redhat.com>
@mergify mergify Bot removed the needs-rebase label Apr 30, 2026
@github-actions

github-actions Bot commented Apr 30, 2026

Copy link
Copy Markdown
Contributor

✱ Stainless preview builds

This PR will update the llama-stack-client SDKs with the following commit message.

feat(interactions): add previous_interaction_id for multi-turn conversations
⚠️ llama-stack-client-openapi studio · code

Your SDK build had at least one "warning" diagnostic.
generate ⚠️

⚠️ llama-stack-client-python studio · code

Your SDK build had at least one "warning" diagnostic.
generate ⚠️build ⏭️lint ⏭️test ✅

⚠️ llama-stack-client-node studio · code

Your SDK build had at least one "warning" diagnostic.
generate ⚠️build ⏭️lint ⏭️test ✅

⚠️ llama-stack-client-go studio · conflict

Your SDK build had at least one warning diagnostic.


This comment is auto-generated by GitHub Actions and is automatically kept up to date as you push.
If you push custom code to the preview branch, re-run this workflow to update the comment.
Last updated: 2026-05-12 08:00:20 UTC

@leseb leseb marked this pull request as ready for review May 5, 2026 19:13
leseb and others added 3 commits May 5, 2026 21:15
… script

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Sébastien Han <seb@redhat.com>

@cdoern cdoern left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

lgtm, one question on some removed tests

Comment thread scripts/test_interactions_api.py
leseb and others added 3 commits May 7, 2026 12:39
The previous_interaction_id test inadvertently replaced the tool calling
test instead of being added alongside it. This restores tool calling
coverage and appends the new test as Test 6.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Sébastien Han <seb@redhat.com>
@leseb leseb requested a review from cdoern May 11, 2026 07:27
@leseb leseb enabled auto-merge May 11, 2026 07:27

@cdoern cdoern left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

lgtm

@leseb leseb added this pull request to the merge queue May 11, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to no response for status checks May 11, 2026
@leseb leseb added this pull request to the merge queue May 11, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks May 11, 2026
@cdoern cdoern added this pull request to the merge queue May 11, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks May 11, 2026
… change

sqlstore_impl was made private in ogx-ai#5776. Use the new
authorized_sqlstore() factory function instead.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Sébastien Han <seb@redhat.com>
@leseb leseb enabled auto-merge May 12, 2026 07:40
@leseb leseb added this pull request to the merge queue May 12, 2026
Merged via the queue into ogx-ai:main with commit f199a03 May 12, 2026
66 checks passed
@leseb leseb deleted the leseb/rhaistrat-1348-v4 branch May 12, 2026 07:57

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Devin Review found 2 potential issues.

View 4 additional findings in Devin Review.

Open in Devin Review

)
messages: list[dict[str, Any]] = list(stored["messages"])
messages.append({"role": "assistant", "content": stored["output_text"]})
messages.extend(self._convert_input_to_openai(None, request.input))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔴 system_instruction silently dropped when previous_interaction_id is provided

In _build_messages at src/ogx/providers/inline/interactions/impl.py:174, when previous_interaction_id is set, self._convert_input_to_openai(None, request.input) is called with None for system_instruction, unconditionally discarding any system_instruction the user provided on the current request. If a user sends both previous_interaction_id and system_instruction, the system instruction is silently ignored with no error or warning. This leads to incorrect behavior where the model doesn't receive the user's intended system prompt.

Prompt for agents
In _build_messages (impl.py around line 163-175), when previous_interaction_id is provided, the system_instruction from the current request is unconditionally dropped by passing None to _convert_input_to_openai on line 174. This silently discards user-provided data.

Two possible approaches:
1. If overriding system_instruction during chaining is intentional behavior, validate that system_instruction is None when previous_interaction_id is set, and raise a ValueError if both are provided so the user gets an explicit error instead of silent data loss.
2. If system_instruction should be allowed during chaining, pass request.system_instruction to _convert_input_to_openai on line 174 instead of None. You may need to handle the case where the stored messages already contain a system message from the previous interaction (e.g., replace it or prepend a new one).
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +168 to +170
raise ValueError(
f"Interaction '{request.previous_interaction_id}' not found. "
"Cannot chain from a non-existent interaction."

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔴 Error message violates AGENTS.md "Failed to ..." prefix rule

AGENTS.md mandates: "Error messages must be prefixed with 'Failed to ...'". The ValueError raised at src/ogx/providers/inline/interactions/impl.py:168-170 uses the message "Interaction '...' not found. Cannot chain from a non-existent interaction." which does not follow this required format.

Suggested change
raise ValueError(
f"Interaction '{request.previous_interaction_id}' not found. "
"Cannot chain from a non-existent interaction."
raise ValueError(
f"Failed to chain interaction: '{request.previous_interaction_id}' not found."
)
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants