New to Kestra?
Use blueprints to kickstart your first workflows.
MCP tool for AI agents to check a governed action request in Postgres, and re-send the Slack approval link when the first approver notification failed.
Status tool of the governed MCP actions pattern: request, approval, status. Setup, secrets and the security model are in mcp-governed-action-request: read it first. Import this flow last, into the same namespace as the other two. Change kestra_url in variables to your own Kestra URL: it is a placeholder (http://localhost:8080), and the re-sent approval link is built from it because kestra.url is unset in Kestra 2.0.4, so left as is it points to localhost.
claim_renotify checks whether the request has been pending_unnotified for more than 10 minutes. If so, it takes the re-send atomically, so concurrent calls send at most one message.renotify_approvers posts the approval link to Slack again and sets the status back to pending. If Slack still fails, the status stays pending_unnotified and the next re-send waits another 10 minutes.read_request reads the row, and row_found builds the response from it, or the unknown response when there is none.governed_action_status, the agent's follow-up call after a production request: status, environment, days and the approval_execution_id.unknown answer for a key that does not exist, with empty values and days 0.AI agents and the people behind them who need to follow up a request without waiting on it, and teams that want a failed approver notification to be retried without adding a scheduler.
The status tool is a flow like any other: the same Postgres query, the same Slack plugin and the same MCP trigger, with the read, the re-send claim and the response in one place, and each call visible as an execution. A failed re-send does not turn the answer into an error for the agent.
On Kestra 2.0.4 OSS with Postgres 16, as a least-privilege role, with a local Slack stub.
claimed, pending, pending_unnotified, running, executed, rejected, expired, failed and unknown.pending.pending_unnotified, and the call still returns the status with isError: false.mcp-governed-action-request, and that flow and the executor imported in the same namespace.PG_PASSWORD and SLACK_WEBHOOK_URL (Slack incoming webhook).variables: jdbc_url, jdbc_user and kestra_url (see above).default.mcp-governed-action-executor, mcp-governed-action-request, then this flow, all into the same namespace.governed_action_request and keep the returned request_id.governed_action_status with that request_id to follow it from pending to executed or rejected.Ideas, not tested in this blueprint:
interval '10 minutes' of the SQL in claim_renotify.renotify_approvers, for example email or a ticket, after the Slack message.governed_requests and checking it in claim_renotify.request_id (STRING, required, ^[A-Za-z0-9_-]{1,64}$): the request_id returned by governed_action_request.status: claimed, pending, pending_unnotified, running, executed, rejected, expired, failed or unknown.environment: staging, production, or empty when unknown.days: the requested number of days, or 0 when unknown.approval_execution_id: the executor execution, empty when unknown or not started yet.readOnly: false.pending or running because the executor was killed or lost needs a manual reset (see the executor flow).This blueprint was created by daiwangk.
