fix(api): keep the Workspace tenant scope for streamed Agent debug runs

The NDJSON debug stream emits its frames after the request handler returned,
so the request-scoped tenant scope is already closed by then. The deferred
execution therefore failed with TenantScopeRequiredError on its first
persistence access and the client only saw a generic runner_error frame with
no log entry.

Re-enter the Workspace tenant scope around the deferred execution and log
unexpected failures with their traceback.
This commit is contained in:
Hyu
2026-09-30 15:47:59 +08:00
parent 05de72570d
commit e3e45d7b34
@@ -26,8 +26,25 @@ def debug_stream_response(service, context, agent_uuid: str, payload: dict) -> q
await queue.put({'kind': 'result', 'data': result})
async def execute() -> None:
application = getattr(service, 'ap', None)
persistence_mgr = getattr(application, 'persistence_mgr', None)
tenant_scope = getattr(persistence_mgr, 'tenant_scope', None)
scope = (
tenant_scope(context.workspace_uuid)
if callable(tenant_scope)
else contextlib.nullcontext()
)
try:
result = await service.debug_agent(context, agent_uuid, payload, on_result=on_result)
# The streamed body is emitted after the request handler returned,
# so the request's tenant scope has already closed: carry the
# trusted Workspace identity into the deferred execution.
async with scope:
result = await service.debug_agent(
context,
agent_uuid,
payload,
on_result=on_result,
)
await queue.put({'kind': 'completed', 'data': result})
except Exception as exc:
# The stream still uses HTTP 200 when execution returns an
@@ -46,6 +63,9 @@ def debug_stream_response(service, context, agent_uuid: str, payload: dict) -> q
elif isinstance(exc, RunnerError):
code, message = 'runner_error', 'The Agent runner could not complete this test'
else:
logger = getattr(application, 'logger', None)
if logger is not None:
logger.exception('Agent debug stream execution failed')
code, message = 'runner_error', 'The Agent debug execution failed'
await queue.put({'kind': 'error', 'code': code, 'msg': message})