Skip to content
⚠️ Before You Start
Risk: High
Duration: 2-4 days
Last Validated: Not yet validated (draft)
Kind: How-to
Risk Note: High (forged callbacks could approve actions)

Deliver approvals in Teams or email and resume the agent from a callback

Draft outline: not validated

Drafted with AI from official sources on 16 Oct 2026. Do not use on a live system until it is written, dry-run by someone other than the author and signed off (planned 2026-12-03). Author: James · dry-run: Prasanna · sign-off: Sivaraj. Work items: AGT-05-T05, AGT-05-T06, AGT-05-T07, AGT-05-T08.

1. Summary

When approvers work in Teams or Outlook and should not need a custom app.

Risk: High (forged callbacks could approve actions). Typical duration: 2-4 days.

2. When to use and when not to

Use it when: When approvers work in Teams or Outlook and should not need a custom app.

Do not use it when: to be written by the author.

3. What you must know first

  • Power Automate approvals support first to respond, everyone must approve, custom responses and sequential types
  • The Standard approvals connector has throttling limits per flow
  • Universal Actions use Action.Execute so one card works in Teams and Outlook
  • The callback must check that an interrupt is still pending before resuming
  • Guest users cannot act on approvals from Outlook email

4. Prerequisites and access

  • Power Automate or a Teams bot registration
  • Callback endpoint with HTTPS and signature verification
  • Approver groups in Entra ID
  • Audit table

5. Steps

Outline of the steps; the author adds the commands and a check after each one.

  1. On interrupt, store an approval record with thread_id and payload
  2. Trigger the flow or bot to send the card to the approver group
  3. Sign the callback payload and verify it at the endpoint
  4. Check the pending interrupt and approver authorisation
  5. Write the audit record, then resume with Command(resume=...)
  6. Update the card to show the outcome
  7. Test duplicate clicks and late clicks after timeout

Draft snippet: Approval callback that verifies, audits and resumes the graph

from fastapi import FastAPI, Header, HTTPException
from langgraph.types import Command
from pydantic import BaseModel

from agent_app.runtime import audit_log, graph, verify_signature

app = FastAPI()


class Decision(BaseModel):
    thread_id: str
    approval_id: str
    type: str  # approve | edit | reject
    approver: str
    comment: str | None = None
    edited_args: dict | None = None


@app.post("/approvals/callback")
def approval_callback(body: Decision, x_signature: str = Header(...)) -> dict:
    if not verify_signature(body.model_dump_json(), x_signature):
        raise HTTPException(status_code=401, detail="bad signature")
    cfg = {"configurable": {"thread_id": body.thread_id}}
    snapshot = graph.get_state(cfg)
    if not snapshot.interrupts:
        raise HTTPException(status_code=409, detail="no pending approval; already decided or expired")
    audit_log(body)  # write before resuming so the decision is never lost
    graph.invoke(Command(resume=body.model_dump()), cfg)
    return {"status": "resumed", "approval_id": body.approval_id}

Snippets to add:

  • snippets/services/approvals/callback.py: FastAPI approval callback (python)
  • snippets/services/approvals/card.json: Adaptive Card with Action.Execute (json)
  • snippets/services/approvals/flow.json: Power Automate flow export (json)

6. Verify it works

A second engineer sends a sandbox approval to a test Teams channel, approves, rejects and double-clicks; pass when each resumes once, the forged callback is refused and every decision is audited.

7. Known issues and fixes

Symptom Likely cause Fix
Approver clicks twice and action runs twice Callback not idempotent Return 409 when no interrupt is pending
Approvals fail to create in bursts Connector throttling Queue requests and respect connector limits
External approver cannot respond Guest user via Outlook Route guests to the portal or a bot card

8. Monitoring and alerts

Signal Alert when Action
Callback signature failures Any Security reviews the source
Approval creation failures More than 3 in 10 minutes Check connector throttling and flow run history

9. AWS and open-source equivalents

On AWS use Step Functions with a task token callback and SNS or Slack for notification. Open-source teams can use a Slack or email webhook with the same callback design.

10. Validation record

Pending. Planned dry-run scenario: A second engineer sends a sandbox approval to a test Teams channel, approves, rejects and double-clicks; pass when each resumes once, the forged callback is refused and every decision is audited.

11. Sources