Skip to content

[release] v0.128.2 - #7976

Merged
mmabrouk merged 154 commits into
mainfrom
release/v0.128.2
Nov 2, 2026
Merged

mmabrouk merged 154 commits into
mainfrom
release/v0.128.2

Conversation

@github-actions

@github-actions github-actions Bot commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

New version v0.128.2 in

  • web
    • web/oss
    • web/ee
    • web/mobile
  • services
  • api
  • sdks
    • sdks/python
  • clients
    • clients/python
    • clients/typescript
  • kubernetes
    • kubernetes/helm

Final QA

  • [fix] Remove the automation version tag and match trigger row borders #7970 In /m, open an agent with a schedule: the Automations card shows no "Runs on ..." tag. Open an agent with an app trigger (for example Slack): its row has the same rounded corners and white fill as a schedule row. Row click and the menu still work. The app trigger row was not captured in the real app.
  • [fix] Keep long agent turns from losing their final message #7943 Set SANDBOX_AGENT_ACP_HEADERS_TIMEOUT_MS=60000 on a runner and start a Claude turn that runs longer than one minute. Pass: the turn fails with an error, the transcript has one copy of the prompt, and the runner log has no ACP write retry line for it. Also confirm a normal long turn (over 60 minutes) keeps its final message.
  • [fix] Close drawer dialogs together with their drawer #7964 In /m, open a drawer (playground, agent config, MCP servers +, Connect server), click outside once. Pass: drawer and dialog both close. Also check Cancel closes only the dialog and agent version history Revert still works.
  • [fix] Fold the agent's in-between messages once the run ends #7958 In /m, run an agent chat (Codex) that writes a short message, calls a tool, then answers. While it runs, every message shows. After it ends, only the final answer shows below the fold and the earlier messages sit in the timeline as thoughts. Also check an embed chat with an approval: the messages stay open until the run resumes.
  • [fix] Keep the Publish drawer steady while the agent list refetches #7957 In /m, open an agent in the playground, then Publish. Pass: the Slack, Telegram and WhatsApp rows show once and do not flash back to skeletons. Then Publish > WhatsApp > Connect and type in Access token. Pass: the field does not move and no loading line shows above it. Also in Settings > Channels, switch the agent in the picker. Pass: rows load for the new agent and each connection names its agent.
  • [fix] Stop skill drawers asking to discard edits nobody made #7963 In /m, import https://github.com/anthropics/skills, open skill-creator and close it. Pass: Save stays off and no "Discard changes?" shows. Type one character: Save turns on and closing asks to discard. Also open a playground prompt editor and check typing still updates the value.
  • [fix] Stop /m navigations from waiting on the middleware #7961 On /m, check sign-in, invites and deep links, because the middleware now matches only entry routes. Sign in with email and with a social provider. Open an /m/invite link signed out and signed in. Open an /m/w/.../sessions/ link signed out, signed in, and with Classic mode on. Pass: sign-in lands in the app, the invite page opens, the deep link opens the right page (the desktop page with Classic mode), and ?view=mobile stays on /m and drops the param. Also click between session tabs. Pass: the tab and URL change at once.
  • [fix] Show skeletons while agent config drawers load #7960 In /m, open an agent in Build on a cold load or throttled network. The configuration pane shows the Configuration bar and row skeletons, not an empty column. Open AGENTS.md, a registry skill, and an integration such as Firecrawl. Each drawer shows a skeleton, then the content. In the AGENTS.md drawer the caret lands in the editor and typing works without a click. Playground prompt editors still render on first load.
  • [fix] Keep the current screen and fresh data on a project switch #7968 In /m, open Settings > AI providers, switch organization from the sidebar switcher. Pass: you stay on AI providers. Then Settings > Integrations, switch project: you stay on Integrations and see that project's connections. Press Back: you land on the previous page in the new project.
  • [feat] Download a skill as SKILL.md or a .zip #7966 In /m, Skills page, open the row menu and choose Download on a skill with no extra files. Pass: you get SKILL.md with name and description. On a multi-file skill (for example slack-gif-creator) you get <name>.zip with one folder holding SKILL.md and every file. In a skill drawer and in the playground, the download icon next to + in the Files header gives the same file. Upload the zip in the New skill flow: it parses back into the same skill. The New skill drawer shows no download icon.
  • [fix] Show a file card for zips and other files the answer links to #7967 In /m, ask an agent to zip a folder with the shell and reply with a markdown link to the zip. Pass: a ZIP card with its size and a Download button shows under the answer, and Download saves the zip. Also run Save as template: the template zip shows as a card. A turn that writes an md with the Write tool and links it shows one md card, not two.
  • [fix] Steer a message sent over any parked dock #7962 In /m, with a permission policy that gates tools, start a run that hits an approval, type a message and send it. Pass: the gate is denied and the agent continues with your message. The approval path was covered by hook tests only. The secret request path was checked live.
  • fix: make Loops contact creation non-blocking #6115 On an EE stage, sign up a new account with a fresh email. Pass: sign-up finishes and opens the app, the contact appears in Loops (or the API log shows a Loops warning and sign-up still succeeds), and other API requests stay responsive during sign-up.
  • [fix] Drain queued messages after a turn the watchdog closes #7965 In /m, send a long prompt to an agent, queue a second message, then restart the runner before the turn ends. After the watchdog closes the turn (about 90 seconds), the queued message runs on its own. Also check that Stop with a queued message leaves it in the dock.
  • fix: map EmbedError subclasses to 400 instead of 500 #7952 Run the acceptance tests in api/oss/tests/pytest/acceptance/workflows/test_workflow_embeds_errors.py on the release preview or staging. They did not run on the fork PR. A pass means the circular, max depth and max embeds tests get 400, and the circular tests see "Circular embed detected" in the detail.
  • [fix] Create template agents without asking to connect apps first #7974 In /m, open Marketplace, pick "PR reviewer", press "Use this template" with GitHub not connected. Pass: you land in the new agent's session, the first turn runs, and no "Connect what it needs" card shows. Then pick a template from the strip on /agents/new: same result.
  • [fix] Refuse skill embeds whose slug and id name different workflows #7959 In /m, commit an agent whose skill embed has one workflow's slug and another workflow's id. Pass: the commit fails with inconsistent_embed_reference and nothing is saved; a normal skill embed still commits and runs.
  • fix(runner): keep Daytona sandboxes active during turns #7627 On a Daytona stage, set AGENTA_RUNNER_DAYTONA_AUTOSTOP_MINUTES low (for example 2) on the runner, then run one agent turn that works for longer than that, for example a shell sleep 300 step. Pass: the turn finishes, the sandbox is still running when it ends, and the runner log has no [daytona] heartbeat failed line. Do it once in a session chat and once as a sessionless run (the cold path). The fix was tested only with mocks.
  • fix(runner): disable GeeseFS multipart expiry for agent drive mounts #7604 On a stage, start an upload of a large file into an agent drive and kill the sandbox mid upload, so SeaweedFS keeps a broken multipart upload. Then start a new agent run on the same store. Pass: the agent drive mounts and the agent sees its files. Also check that the cloud buckets have a lifecycle rule that deletes incomplete multipart uploads, because geesefs no longer cleans them up at mount time.
  • fix(frontend): keep Other write-in box visible after clearing text on reload #7955 In /m onboarding, pick "Other" on "What best describes you?" or "How did you hear about Agenta?", type a line, reload, then clear the box. Pass: the box stays open, the Other chip stays on, Continue is disabled, and pressing a letter key does not pick another chip. Picking another chip then closes the box.
  • fix(api): add socket timeout and health check to the durable Redis streams client #7587 On staging, leave the stream workers idle for 5 minutes, then send a few agent turns and traces. Pass: the worker logs show no "Failed to read batch" or "Failed to accumulate batch" errors while idle, traces and session records arrive, and a session live view stays connected for more than 30 seconds. This checks that the new 15 s Redis socket timeout does not cut normal blocking reads.
  • feat(api): stop reading workspaces (M4b step 2b) #7882 Migrations on staging data: after the deploy, alembic_version shows oss000000062 and ee0000000009; every organization has at most one is_default project; no project points at a workspace of another organization; no meters row has a workspace_id; meter sums equal the pre-deploy dump.
  • feat(api): stop reading workspaces (M4b step 2b) #7882 In /m on staging: sign up, create an agent, chat with it, invite a second account and accept the invitation, change its role, remove it. Pass: no 4xx or 5xx in the network panel. The PR's live QA could not open the /m chat screen on its dev stack, so the chat step is new here.
  • feat(api): stop reading workspaces (M4b step 2b) #7882 Old ids: open /m/w/<old workspace id>/p/<project>/agents (pass: the app rewrites it to the organization id) and call the API with ?workspace_id=<old workspace id> (pass: 401; with the organization id: 200).
  • feat(api): stop reading workspaces (M4b step 2b) #7882 A Claude subscription agent turn through the product endpoint (the PR only tested the ChatGPT subscription), and the four acceptance tests that timed out under load on the PR's stack: mounts/test_attachments_mount_hidden.py, mounts/test_mount_storage_prefix_hidden.py, loadables/test_loadable_strategies.py (edge b2 windowing), sharing/test_private_session_probe.py (rbac-secret).
  • fix(api): bump certifi and litellm in api/uv.lock (Dependabot alerts) #7949 After deploy, open a mount in /m, write a file, list it and delete it (checks storage delete after the miniopy-async and certifi change). A pass is a normal delete with no error. Also check the Dependabot alerts for certifi and litellm on api/uv.lock close.

Deploy steps

shafeeq27edu-ai and others added 30 commits August 19, 2026 17:15
AuthService is imported locally inside create_accounts(), so it is
not an attribute of oss.src.services.commoners. Patch the defining
module instead: oss.src.core.auth.service.AuthService.
LoopsConfig.enabled is a read-only property with no setter.
Instantiating a real LoopsConfig() and setting .enabled crashed with:
AttributeError: property 'enabled' of 'LoopsConfig' object has no setter

Replaced real instantiation with MagicMock() in all 3 tests:
- test_add_contact_success
- test_add_contact_retries_on_429_then_succeeds
- test_add_contact_exhausts_retries
…reams client

The Redis client used for the durable streams had no socket timeout and no
health check. The streams worker (entrypoints/worker_streams.py) passed
socket_timeout=None explicitly, which means "wait forever". After a managed
Redis failover, an open connection can stop answering without ever closing,
and any call on it (XREADGROUP, XACK, heartbeat) then waits indefinitely, so
the worker stalls with no error and never reaches its retry path.

Add streams_client_options() in oss/src/dbs/redis/shared/engine.py:
socket_timeout=15s, health_check_interval=30s, socket_keepalive=True. The
read timeout is longer than the XREADGROUP block (max_block_ms=5000 in
StreamConsumer), so a normal idle blocking read does not time out. Use it for
both StreamsEngine.get_redis() and the worker's own client.

A timed-out call now raises redis.exceptions.TimeoutError. StreamConsumer
already catches Exception in read_batch() and run() and retries after a 1s
sleep, so the consumer reconnects and continues without further changes.

Tests (api/oss/tests/pytest/unit/test_redis_streams_client_options.py):
- the option values, and that both clients are built from them
- a client against a server that accepts and never answers raises
  RedisTimeoutError within 2s. With the options removed this test and two
  others fail. redis-py 8.0.1 (pinned in uv.lock) falls back to a 5s default
  when socket_timeout is omitted, and hangs forever with socket_timeout=None,
  which is what the worker was passing.

Not covered: no test against a real Redis failover, and none that drives
StreamConsumer through a timeout end to end; the retry behaviour is from
reading read_batch()/run(), not from a new test.

Fixes #7535
…annel limits

M7: person or project accounts (caller_account, project_default), personal MCP servers, custom secrets wait for hidden secrets, durable-work edit rule. M6a: installation turns keep today's role. M6 and M9 prerequisites match CONTRACT section 14. CONTRACT: channel rules, gateway always on, no save-time checks. New changes agent-needs-setup and channel-limits (M10).
…pace_id and meters.workspace_id (M4b step 2b)

No deployed code reads or writes the workspace storage any more, so step 3 can drop it
while these pods serve. A legacy workspace id is now an unknown id: the Bearer
workspace parameter, accept links and the admin graph take the organization id only.
The runtime ORM no longer maps the dropped objects; the legacy core-chain data
migrations use their frozen models instead. oss000000055 and ee0000000008 rerun the
step-2 repair, one-default consolidation and meter fold for rows that step-1 pods
wrote during the step-2 rollout.
A channel turn uses the linked user's own account and refuses an
unlinked user at run time, with no check when a channel binding is
saved. Personal MCP servers use the reference scope user. The
durable-work edit rule covers API-key work. M7 no longer waits for M6:
until M6a, an API-key run has no person.
The owner rule is no checks at save time. A revision with the specific
binding or an unsupported binding saves, and its run is refused at run
start.
…s (M7)

A schedule, a trigger subscription or an evaluation run executes as its stored
principal. Edits that change what it executes (target, inputs, event, connection,
evaluation configuration) are now refused unless the request comes from that
principal. Others with the edit capability can still rename, pause, stop or
delete the work. The refusal (403 owner_only) names the person the work runs as,
and /m shows that sentence when an automation save is refused.
Codex review: dropping nulls and comparing with Python equality let a null input
or a true-to-1 change pass as no change, and the check ran before the DAO locked
the row. The comparison now uses canonical JSON, and the trigger DAOs run the
check on the row they lock for the write.
Codex round 2: the evaluation edit compared against an unlocked read. The DAO
now locks the run for a user edit and runs the check on that row.
Review loop round 1: the simple evaluation edit rebuilt the run configuration
from targets read before a stop and a wait, then wrote it without a locked
check, so a rename could undo a concurrent change by the executing principal.
The final write now refuses when the locked run changed since the read, unless
the editor is the executing principal. The early duplicate checks before the
locked ones are removed for schedules and evaluation runs.
Review loop round 2: the rename rebuilt the configuration from targets read
before a second read, so a change between the two reads could still be undone,
and the rebuild dropped concurrency and inferred schemas. An edit that does not
change the targets now writes the configuration as stored, and edit_run checks
it against the locked row with the editor, which refuses it when the executing
principal changed the run in between.
…ser batches

- An edit that sends no configuration leaves it as it is, so it is a lifecycle edit.
- Simple evaluation targets compare by their ids, so a list and the stored map of
  the same ids are equal.
- A user's batch edit writes run by run, each checked on its locked row.
Every agent connection reference can name its binding: caller_account (each
person's own account) or project_default (the project's shared account, the
default). The server derives the caller_account bindings from the resolved
revision in _prepare_invoke, signs them into the run credential as
gateway_bindings, and copies them at every re-mint. A lookup without a signed
binding stays the project's shared account; a caller_account connection whose
run carries none is refused, never answered with the shared account.

People can store their own provider key per organization (secrets.user_id,
scope=user on the vault create, list and delete routes). The LLM gateway gets a
user namespace that answers the run's person's own key only for a bound model
connection. A human run uses that human; a channel turn uses the linked
person; an API key run and an unlinked channel user are refused.

Gated by AGENTA_ACCESS_PERSONAL_CREDENTIALS_ENABLED (default off) and, in EE,
the organization flag allow_personal_credentials (default on). Unsupported
bindings (specific, a personal account on an organization connection, a
personal subscription login for now) are refused as a format error at commit
and again at run start.
… yet

Codex review: Composio and MCP caller_account bindings were signed but the run
path still resolved the project's connection, and the SDK's vault fallback could
answer the project's key for a personal model connection. Both now refuse. The
organization slug index is rebuilt under a temporary name so organization slugs
stay unique during the migration.
…e binding parse

Review loop round 1 (simplify and slop):
- Personal MCP is deferred, so the SDK keeps MCPGatewayConnection as before and the
  server refuses any personal MCP reference without building a claim for it.
- No module flags: a personal Composio binding is refused here and served in the
  personal connections change.
- PersonalCredentialRefused is the one refusal type on the LLM plane too.
- _prepare_invoke parses the bindings once.
- Comment and route placement fixes.
…gned-binding refusal

Review loop round 2: a directly invoked SDK agent could name a project
subscription slug with caller_account and get the shared login. The Connection
model now refuses caller_account with mode self_managed. The unsigned-binding
refusal is built in one place, and the binding parser is named for what it
returns.
- The personal-credentials policy stops new personal keys, not a person listing or
  removing the ones they stored.
- A person's own key is always write-only.
- A workflow-tool child whose binding is refused answers that refusal, not a
  generic failure.
- The SDK refuses a personal model connection that the gateway answered outside
  the user namespace (an API that predates bindings).
The owner rule is no checks at save time. A revision with an unsupported binding
now saves; the run that uses it is refused with binding_not_supported.
mmabrouk and others added 19 commits November 2, 2026 16:01
[fix] Show a file card for zips and other files the answer links to
[fix] Steer a message sent over any parked dock
The new test renders the question with a saved Other answer, clears the
text box, and checks that the box stays open and a letter key does not
pick another choice. Both checks fail on the code before the fix.
…ns too

Move the activity heartbeat into withDaytonaActivityHeartbeat and wrap every
runTurn entry point with it: the keep-alive dispatch, its runCold path, and
runSandboxAgent. Before, only the keep-alive dispatch had it.
fix: make Loops contact creation non-blocking
[fix] Drain queued messages after a turn the watchdog closes
…t_keepalive

A unix:// Redis URL rejects socket_keepalive, and redis-py already enables
keepalive for TCP. A failed accumulation read in read_batch dropped the entries
the first read had returned, and they stayed pending.
fix: map EmbedError subclasses to 400 instead of 500
…t-gate

[fix] Create template agents without asking to connect apps first
[fix] Refuse skill embeds whose slug and id name different workflows
…stop

fix(runner): keep Daytona sandboxes active during turns
…piry

fix(runner): disable GeeseFS multipart expiry for agent drive mounts
fix(frontend): keep Other write-in box visible after clearing text on reload
…timeout

fix(api): add socket timeout and health check to the durable Redis streams client
fix(runner): bump zod to 4.6.6 (Dependabot alert #1866)
@github-actions

github-actions Bot commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor Author

Railway Preview Environment

Item Value
Status stopped
Commit 5d3b904f17e80c70f2b8790086322431640b86ae
Manual expiry (UTC) Not granted
CI deadline (UTC) Not granted
Workflow https://github.com/Agenta-AI/agenta/actions/runs/41500420990

PR closed or converted to draft. Environment absence verified; retained storage requires separate provider accounting.

Post /preview as a new comment to request a one-hour preview. Repeating it while active does not extend the hour.
Preview data is disposable. Expiry is enforced by the next successful cleanup sweep, not an exact timer.
Environment deletion stops its compute. Provider-retained storage and permanent services may still be billed.

mmabrouk and others added 8 commits November 2, 2026 16:56
feat(api): stop reading workspaces (M4b step 2b)
docs(sharing): specs for the 2026-10-26 decisions, needs setup and channel limits
Keeps the release branch's tasks.md: task 2.1 now covers more than the
SecretMode removal, so this PR no longer ticks it.
…tellm-otel

fix(api): bump certifi and litellm in api/uv.lock (Dependabot alerts)
refactor(api): remove SecretMode from the secrets resolver
origin is the public repository. With the shared config from #7873, every
git push from a checkout also pushed refs/entire/checkpoints/* with the full
agent transcript, which carries internal details. Keep checkpoints local until
they have a private remote.

Entire-Checkpoint: 01M6EKKZJJY7E7D5VT3PAF3HW6
…n-push

chore: stop Entire from pushing session transcripts to origin

@mmabrouk mmabrouk left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

🤖 The AI agent says: Approved on Mahmoud's instruction after the v0.128.2 production deploy went green in US (run 41500497682) and EU (run 41502633804), with the live check passing every turn in both regions.

@mmabrouk
mmabrouk merged commit 36d779a into main Nov 2, 2026
85 of 90 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.

6 participants