Skip to content

feat: add session-name input for message reuse#3

Merged
Gkrumbach07 merged 5 commits intomainfrom
feat/inactivity-timeout
Apr 3, 2026
Merged

feat: add session-name input for message reuse#3
Gkrumbach07 merged 5 commits intomainfrom
feat/inactivity-timeout

Conversation

@Gkrumbach07
Copy link
Copy Markdown
Contributor

Summary

  • Add session-name input — when provided, sends the prompt as a message to an existing session instead of creating a new one
  • Uses the AG-UI /agui/run endpoint to deliver messages
  • Supports --wait to poll after sending

Test plan

  • Create session without session-name — works as before
  • Pass session-name — verify message delivered to existing session
  • Pass session-name with wait: true — verify polling works

🤖 Generated with Claude Code

Ambient Code Bot and others added 2 commits April 2, 2026 17:57
Change the `timeout` input from a hard session timeout (minutes) to an
inactivity timeout (seconds). The session now runs as long as needed and
auto-stops after the specified duration of inactivity.

- `timeout` now maps to `inactivityTimeout` in the API body (was `timeout`)
- Value is passed in seconds with no conversion (was minutes * 60)
- Default is `0` (no auto-stop) for backward compatibility
- Recommended value for orchestrator sessions: `60` (1 min idle → stop)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When session-name is provided, the action sends the prompt as a message
to that existing session via the AG-UI /agui/run endpoint instead of
creating a new session.

- New input: session-name (optional)
- New function: send_message() posts to /agui/run
- Supports --wait to poll after sending
- Falls back to create mode when session-name is empty

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 2, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 576da64a-8202-48f1-a31e-743a2b046117

📥 Commits

Reviewing files that changed from the base of the PR and between 2afe3b8 and 81cc39b.

📒 Files selected for processing (1)
  • create_session.py

Walkthrough

Adds optional session-name and poll-timeout inputs to the action and extends create_session.py to optionally send a message to an existing session (skipping creation), add session lifecycle helpers (get/start/ensure/send), and use poll-timeout for wait/poll behavior. (≤50 words)

Changes

Cohort / File(s) Summary
Action inputs
action.yml
Added optional inputs.session-name (default '') and inputs.poll-timeout (default '60'); updated inputs.prompt description to indicate it can start a session or send a message to an existing session.
Session messaging & CLI behavior
create_session.py
Added CLI options --session-name and --poll-timeout. Added helpers: get_session_phase, start_session, ensure_session_running, send_message. Main flow now branches to create-a-session or send-a-message, uses poll_timeout for both startup waiting and --wait polling, and emits MessageSent/MessageFailed phases.

Sequence Diagram

sequenceDiagram
    participant Action as GitHub Action
    participant Script as create_session.py
    participant AGUI as AG-UI API

    Action->>Script: Run with prompt (+ optional --session-name, --wait, --poll-timeout)
    alt --session-name provided
        Script->>AGUI: GET /sessions/{name} (read phase)
        AGUI-->>Script: phase or 404
        alt phase != "Running"
            Script->>AGUI: POST /sessions/{name}/start
            AGUI-->>Script: start response
            Script->>AGUI: poll GET /sessions/{name} (up to --poll-timeout)
            AGUI-->>Script: phase updates
        end
        Script->>AGUI: POST /agui/run (send user message with runId + message id)
        AGUI-->>Script: send response (success/failure)
        alt --wait set
            Script->>AGUI: poll GET /sessions/{name} until final or timeout (--poll-timeout)
            AGUI-->>Script: final status
        end
    else no --session-name
        Script->>AGUI: POST /sessions (create with inactivityTimeout from --timeout)
        AGUI-->>Script: create response (session name)
        Script->>AGUI: poll GET /sessions/{new} (up to --poll-timeout)
        AGUI-->>Script: phase updates
    end
    Script->>Action: emit outputs (`session_phase`, `session_name`, exit code)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: adding a session-name input to enable message reuse with existing sessions instead of creating new ones.
Description check ✅ Passed The description is clearly related to the changeset, explaining the new session-name input functionality, the AG-UI endpoint used, and the test plan.
Docstring Coverage ✅ Passed Docstring coverage is 83.33% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/inactivity-timeout

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@action.yml`:
- Line 105: The composite action currently hard-codes the create_session.py
polling timeout because action.yml only forwards session-name
(INPUT_SESSION_NAME); add a new input named poll-timeout in action.yml and
expose it (e.g., INPUT_POLL_TIMEOUT) and then forward that value into the step
that invokes create_session.py (either as an environment variable or by
appending --poll-timeout ${{ inputs.poll-timeout }} to the command that runs
create_session.py in the composite action), and update the other input
mappings/steps referenced near the same block (the places around
INPUT_SESSION_NAME and the later occurrences) so the poll-timeout is passed
consistently into the wait flow.

In `@create_session.py`:
- Around line 38-42: The URL is built with raw project and session_name which
can contain reserved characters; update the code that constructs the url
variable to percent-encode path segments (project and session_name) before
interpolation (e.g., use urllib.parse.quote on project and session_name) so
reserved characters like '/', '?', '#', and spaces are encoded; ensure you
encode only the path segments (not the whole URL or query string) and then use
the encoded values when assigning url =
f"{api_url.rstrip('/')}/projects/{encoded_project}/agentic-sessions/{encoded_session_name}/agui/run".
- Around line 253-265: The --wait path currently calls poll_session() which only
checks overall session phase and can return a stale terminal state; modify the
flow around send_message and poll_session so that the newly-created run is
tracked and waited-for specifically: capture the session phase immediately
before calling send_message (use the same variable sent by send_message that
contains runId), extract the generated runId returned by send_message, and then
when args.wait is set either (a) subscribe to SSE RUN_FINISHED events and wait
for an event whose runId matches the returned runId, or (b) poll the specific
run status (not poll_session()) until that runId reports terminal state; update
the code paths referencing send_message, runId, and poll_session to perform
run-level waiting rather than relying solely on session-level phase.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: d999e8c8-2956-472a-8476-88518bfa77fb

📥 Commits

Reviewing files that changed from the base of the PR and between ab7111b and dec22dc.

📒 Files selected for processing (2)
  • action.yml
  • create_session.py

Comment thread action.yml
Comment thread create_session.py
Comment on lines +38 to +42
url = f"{api_url.rstrip('/')}/projects/{project}/agentic-sessions/{session_name}/agui/run"

body = {
"threadId": session_name,
"runId": str(uuid.uuid4()),
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

URL path parameters must be percent-encoded before request construction.

Line 38 builds the endpoint using raw project and session_name. If either contains reserved characters (/, ?, #, spaces), requests can target the wrong route or fail unpredictably.

🔧 Proposed fix
+from urllib.parse import quote
 ...
-    url = f"{api_url.rstrip('/')}/projects/{project}/agentic-sessions/{session_name}/agui/run"
+    encoded_project = quote(project, safe="")
+    encoded_session_name = quote(session_name, safe="")
+    url = (
+        f"{api_url.rstrip('/')}/projects/{encoded_project}"
+        f"/agentic-sessions/{encoded_session_name}/agui/run"
+    )
As per coding guidelines, "Focus on major issues impacting performance, readability, maintainability and security. Avoid nitpicks and avoid verbosity."
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@create_session.py` around lines 38 - 42, The URL is built with raw project
and session_name which can contain reserved characters; update the code that
constructs the url variable to percent-encode path segments (project and
session_name) before interpolation (e.g., use urllib.parse.quote on project and
session_name) so reserved characters like '/', '?', '#', and spaces are encoded;
ensure you encode only the path segments (not the whole URL or query string) and
then use the encoded values when assigning url =
f"{api_url.rstrip('/')}/projects/{encoded_project}/agentic-sessions/{encoded_session_name}/agui/run".

Comment thread create_session.py
Comment on lines +253 to +265
if args.wait:
poll_result = poll_session(
api_url=args.api_url,
api_token=args.api_token,
project=args.project,
session_name=args.session_name,
poll_interval=args.poll_interval,
timeout_minutes=args.poll_timeout,
verify_ssl=verify_ssl,
)
output["session_phase"] = poll_result.get("phase", "")
output["session_result"] = poll_result.get("result", "")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

Ambient Code AG-UI API: after POST /agui/run with runId, what endpoint and field should be polled to determine completion of that specific runId (not just session phase)?

💡 Result:

No specific endpoint found for polling individual runId completion in Ambient Code AG-UI API. Standard AG-UI protocol uses streaming SSE from POST /agui (or /agui/run) where completion is indicated by RUN_FINISHED or run_finished event containing the runId. For polling a specific runId (not session), no dedicated endpoint identified in available sources. Ambient Code Platform uses Kubernetes CRDs for agentic sessions with public API via public-api gateway for status/metrics, but no explicit /agui/run poll endpoint documented. Likely poll GET /sessions/{runId} or similar via their public API, but unconfirmed. Use SSE streaming for real-time completion detection matching runId in events.

Citations:


🏁 Script executed:

# First, find the create_session.py file
fd "create_session.py" -type f

Repository: ambient-code/ambient-action

Length of output: 241


🏁 Script executed:

fd "create_session.py"

Repository: ambient-code/ambient-action

Length of output: 88


🏁 Script executed:

wc -l create_session.py

Repository: ambient-code/ambient-action

Length of output: 92


🏁 Script executed:

cat -n create_session.py

Repository: ambient-code/ambient-action

Length of output: 12821


--wait after send_message cannot confirm the submitted runId completed; it returns stale session phase.

The generated runId (line 42) is never tracked or correlated with polling. When --wait is set (line 253), poll_session() checks only the session's overall phase; if the session was already terminal before the message was sent, polling immediately returns that old completion state, not the result of the just-submitted run.

The web search indicates AG-UI uses SSE streaming with RUN_FINISHED events for reliable run completion detection (matching the runId in events). If polling is preferred, either switch to SSE streaming or add pre-send phase capture and post-send phase-transition confirmation before accepting terminal completion.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@create_session.py` around lines 253 - 265, The --wait path currently calls
poll_session() which only checks overall session phase and can return a stale
terminal state; modify the flow around send_message and poll_session so that the
newly-created run is tracked and waited-for specifically: capture the session
phase immediately before calling send_message (use the same variable sent by
send_message that contains runId), extract the generated runId returned by
send_message, and then when args.wait is set either (a) subscribe to SSE
RUN_FINISHED events and wait for an event whose runId matches the returned
runId, or (b) poll the specific run status (not poll_session()) until that runId
reports terminal state; update the code paths referencing send_message, runId,
and poll_session to perform run-level waiting rather than relying solely on
session-level phase.

When session-name targets a stopped session, the action now:
1. Checks session phase via GET /agentic-sessions/{name}
2. If stopped, calls POST /agentic-sessions/{name}/start
3. Waits up to 60s for Running phase
4. Then sends the message

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

♻️ Duplicate comments (2)
create_session.py (2)

37-44: ⚠️ Potential issue | 🟠 Major

Percent-encode project and session_name before building request URLs.

These values are still interpolated raw here. If either contains /, ?, #, or spaces, the request can hit the wrong route or fail outright. The same bug is repeated in the new /start and /agui/run helpers, so please encode the path segments once and reuse them everywhere.

🔧 Proposed fix
+from urllib.parse import quote
...
-    url = f"{api_url.rstrip('/')}/projects/{project}/agentic-sessions/{session_name}"
+    encoded_project = quote(project, safe="")
+    encoded_session_name = quote(session_name, safe="")
+    url = (
+        f"{api_url.rstrip('/')}/projects/{encoded_project}"
+        f"/agentic-sessions/{encoded_session_name}"
+    )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@create_session.py` around lines 37 - 44, The code builds request URLs by
interpolating raw path segments (project, session_name) into url (in
create_session.py where url =
f"{api_url.rstrip('/')}/projects/{project}/agentic-sessions/{session_name}" and
in the /start and /agui/run helpers), which breaks when segments contain '/',
'?', '#', or spaces; fix by percent-encoding those path segments once (e.g.,
using urllib.parse.quote) before composing URLs, centralize this encoding into a
helper (e.g., encode_path_segment or similar) and use that helper everywhere the
project or session_name is inserted into path strings so all requests use
encoded path segments consistently.

121-160: ⚠️ Potential issue | 🟠 Major

--wait is still waiting on session state, not on the message run you just submitted.

send_message() creates a fresh runId but returns only True/False, and the wait path then polls only session.status.phase. If the session was already Completed from an earlier run, --wait can return that stale terminal state immediately even though the new message run has not finished. Return the submitted runId from send_message() and wait on run-specific completion instead of session-level phase.

Ambient Code official AG-UI documentation: after POST /projects/{project}/agentic-sessions/{session}/agui/run with a runId, what documented mechanism or endpoint should a client use to detect completion of that specific runId?

Also applies to: 348-359

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@create_session.py`:
- Line 303: The new parser.add_argument("--poll-timeout", ...) is never reached
from the composite action because action.yml still exposes/forwards only the old
timeout/poll-interval inputs, so args.poll_timeout always falls back to the 60
default; fix either by updating action.yml to add a poll-timeout input and
forward it into the script (match the naming used by parser.add_argument) or
make create_session.py backward-compatible by changing the wait branches to use
args.poll_timeout if set else fall back to args.timeout (check args.poll_timeout
presence before using it), ensuring variables args.poll_timeout and args.timeout
are referenced where polling timeout is read so existing users still get the
intended behavior.
- Around line 96-118: The current logic returns True for any non-terminal phase,
allowing callers to proceed before the session is Running; change the tail of
the function (the branch that currently does logger.info(f"Session
{session_name} is in phase {phase}, waiting...") followed by return True) to
poll with the same deadline logic used after start_session: repeatedly call
get_session_phase(api_url, api_token, project, session_name, verify_ssl)
(sleeping ~3s between tries) until phase == "Running" (then return True), or
phase becomes None or the timeout expires (log an error and return False); reuse
the existing max_wait/deadline pattern and keep the logging messages consistent
with the start branch and functions start_session and get_session_phase.

---

Duplicate comments:
In `@create_session.py`:
- Around line 37-44: The code builds request URLs by interpolating raw path
segments (project, session_name) into url (in create_session.py where url =
f"{api_url.rstrip('/')}/projects/{project}/agentic-sessions/{session_name}" and
in the /start and /agui/run helpers), which breaks when segments contain '/',
'?', '#', or spaces; fix by percent-encoding those path segments once (e.g.,
using urllib.parse.quote) before composing URLs, centralize this encoding into a
helper (e.g., encode_path_segment or similar) and use that helper everywhere the
project or session_name is inserted into path strings so all requests use
encoded path segments consistently.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 9588844a-5bd4-459c-a012-f3c7e01fa3d5

📥 Commits

Reviewing files that changed from the base of the PR and between dec22dc and 5a8b099.

📒 Files selected for processing (1)
  • create_session.py

Comment thread create_session.py Outdated
Comment thread create_session.py
- Expose poll-timeout input in action.yml and wire through to script
- Fix ensure_session_running to always poll until Running phase,
  not fall through for Pending/Starting phases

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (2)
create_session.py (2)

29-37: ⚠️ Potential issue | 🟠 Major

Percent-encode these path segments before building the request URL.

Line 37 and the similar URL builders on Lines 62, 130, and 230 still interpolate raw project / session_name. Names containing /, space, ?, or # can hit the wrong route or 404, which makes the new reuse flow fail for valid identifiers. Encode each path segment once before interpolation and reuse the encoded values in all four helpers.

🔧 Proposed fix
+from urllib.parse import quote
...
-    url = f"{api_url.rstrip('/')}/projects/{project}/agentic-sessions/{session_name}"
+    encoded_project = quote(project, safe="")
+    encoded_session_name = quote(session_name, safe="")
+    url = (
+        f"{api_url.rstrip('/')}/projects/{encoded_project}"
+        f"/agentic-sessions/{encoded_session_name}"
+    )

Also applies to: 54-63, 130-130, 220-230

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@create_session.py` around lines 29 - 37, Percent-encode the path segments
before building the request URL so project and session_name don’t break routes;
in get_session_phase (and the other helpers that build URLs around the same
inputs at the other occurrences) call a single percent-encoding step for project
and session_name (reuse the encoded values) and interpolate those encoded
variables into url =
f"{api_url.rstrip('/')}/projects/{encoded_project}/agentic-sessions/{encoded_session_name}"
instead of inserting raw project/session_name; ensure you use a standard
percent-encoding routine that encodes reserved characters (e.g., via
urllib.parse.quote) and apply the same change to the other functions that
construct URLs with project/session_name.

118-157: ⚠️ Potential issue | 🟠 Major

--wait cannot tell whether the message submitted here is the one that finished.

Line 134 creates a unique runId, but send_message() returns only True / False. The later wait path can therefore poll only session-level state, which is ambiguous once multiple messages can target the same session. Return the runId here and wait on that specific run instead of whole-session phase.

🔧 Minimal root-cause change
 def send_message(
@@
-) -> bool:
+) -> str | None:
@@
-    body = {
+    run_id = str(uuid.uuid4())
+    body = {
         "threadId": session_name,
-        "runId": str(uuid.uuid4()),
+        "runId": run_id,
@@
-        return True
+        return run_id
@@
-        return False
+        return None
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@create_session.py` around lines 118 - 157, send_message currently generates a
unique runId but only returns True/False, making later --wait polling ambiguous;
change send_message(api_url, api_token, project, session_name, message,
verify_ssl=True) to return the generated runId (string) on success and
None/False on failure so callers can poll that specific run; specifically,
extract runId into a variable (e.g., run_id = str(uuid.uuid4())), use run_id in
the body["runId"], and replace the boolean return with return run_id after a
successful resp.raise_for_status(); ensure callers that used the boolean now
expect and handle a run id (or None) to wait on the precise run.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@create_session.py`:
- Around line 323-332: The send_message() call in the reused-session path
ignores the caller's startup wait budget (it inherits
ensure_session_running(..., max_wait=60)), so add a startup timeout parameter
and thread the caller's poll timeout through it: update send_message(...) to
accept startup_timeout (or a dedicated startup_timeout flag), pass that value
from main() (e.g., startup_timeout=args.poll_timeout or a new CLI arg), and
ensure send_message uses startup_timeout when calling
ensure_session_running(..., max_wait=startup_timeout); update any other callers
of send_message accordingly.

---

Duplicate comments:
In `@create_session.py`:
- Around line 29-37: Percent-encode the path segments before building the
request URL so project and session_name don’t break routes; in get_session_phase
(and the other helpers that build URLs around the same inputs at the other
occurrences) call a single percent-encoding step for project and session_name
(reuse the encoded values) and interpolate those encoded variables into url =
f"{api_url.rstrip('/')}/projects/{encoded_project}/agentic-sessions/{encoded_session_name}"
instead of inserting raw project/session_name; ensure you use a standard
percent-encoding routine that encodes reserved characters (e.g., via
urllib.parse.quote) and apply the same change to the other functions that
construct URLs with project/session_name.
- Around line 118-157: send_message currently generates a unique runId but only
returns True/False, making later --wait polling ambiguous; change
send_message(api_url, api_token, project, session_name, message,
verify_ssl=True) to return the generated runId (string) on success and
None/False on failure so callers can poll that specific run; specifically,
extract runId into a variable (e.g., run_id = str(uuid.uuid4())), use run_id in
the body["runId"], and replace the boolean return with return run_id after a
successful resp.raise_for_status(); ensure callers that used the boolean now
expect and handle a run id (or None) to wait on the precise run.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 806ffb2e-cf97-4f3f-a598-e03403d3f2fa

📥 Commits

Reviewing files that changed from the base of the PR and between 5a8b099 and 2afe3b8.

📒 Files selected for processing (2)
  • action.yml
  • create_session.py

Comment thread create_session.py
send_message now accepts startup_timeout parameter instead of
hardcoding 60s. main() passes poll_timeout (converted to seconds)
so callers can control how long to wait for a stopped session to restart.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@Gkrumbach07 Gkrumbach07 merged commit 1204c23 into main Apr 3, 2026
3 checks passed
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.

1 participant