From 8db9f25db2961942e9ad594c51ae2e80100ec33a Mon Sep 17 00:00:00 2001 From: Abhimanyu Saharan Date: Fri, 13 Feb 2026 02:35:52 +0530 Subject: [PATCH] feat: add tag assignment deletion and improve agent error handling in provisioning --- backend/app/services/board_lifecycle.py | 9 +++++++++ backend/app/services/openclaw/provisioning.py | 15 ++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/backend/app/services/board_lifecycle.py b/backend/app/services/board_lifecycle.py index ea59e14e..1c5ca94f 100644 --- a/backend/app/services/board_lifecycle.py +++ b/backend/app/services/board_lifecycle.py @@ -22,6 +22,7 @@ from app.models.board_webhook_payloads import BoardWebhookPayload from app.models.board_webhooks import BoardWebhook from app.models.organization_board_access import OrganizationBoardAccess from app.models.organization_invite_board_access import OrganizationInviteBoardAccess +from app.models.tag_assignments import TagAssignment from app.models.task_dependencies import TaskDependency from app.models.task_fingerprints import TaskFingerprint from app.models.tasks import Task @@ -64,6 +65,14 @@ async def delete_board(session: AsyncSession, *, board: Board) -> OkResponse: col(ActivityEvent.task_id).in_(task_ids), commit=False, ) + await crud.delete_where( + session, + TagAssignment, + col(TagAssignment.task_id).in_(task_ids), + commit=False, + ) + # Keep teardown ordered around FK/reference chains so dependent rows are gone + # before deleting their parent task/agent/board records. await crud.delete_where( session, TaskDependency, diff --git a/backend/app/services/openclaw/provisioning.py b/backend/app/services/openclaw/provisioning.py index 96becad5..2c9bc963 100644 --- a/backend/app/services/openclaw/provisioning.py +++ b/backend/app/services/openclaw/provisioning.py @@ -73,6 +73,15 @@ def _is_missing_session_error(exc: OpenClawGatewayError) -> bool: ) +def _is_missing_agent_error(exc: OpenClawGatewayError) -> bool: + message = str(exc).lower() + if not message: + return False + if any(marker in message for marker in ("unknown agent", "no such agent", "agent does not exist")): + return True + return "agent" in message and "not found" in message + + def _repo_root() -> Path: return Path(__file__).resolve().parents[3] @@ -880,7 +889,11 @@ class OpenClawGatewayProvisioner: agent_gateway_id = GatewayAgentIdentity.openclaw_agent_id(gateway) else: agent_gateway_id = _agent_key(agent) - await control_plane.delete_agent(agent_gateway_id, delete_files=delete_files) + try: + await control_plane.delete_agent(agent_gateway_id, delete_files=delete_files) + except OpenClawGatewayError as exc: + if not _is_missing_agent_error(exc): + raise if delete_session: if agent.board_id is None: