ApprovalLoop — Autonomous Approval Chasing

Most agents wait for a prompt. ApprovalLoop acts when nothing happens.

Inspiration

In enterprise workflows, the biggest source of operational drag isn't always complex decision-making. Often, it's human inaction.

An expense report, purchase order, or access request can be submitted correctly and still remain stuck because the designated approver is traveling, overloaded with meetings, or simply hasn't seen it.

And nobody prompts an AI chatbot because nobody is watching the clock.

We asked:

Why should agents wait for a user prompt when the clock itself can be an authoritative trigger?

That question led to ApprovalLoop, an autonomous approval agent designed for workflows where inaction itself is a signal.

Our core thesis is simple:

Most agents wait for a prompt. ApprovalLoop acts when nothing happens.


What It Does

ApprovalLoop is an autonomous enterprise approval agent that runs as a background workflow on Google Cloud without requiring a human prompt for each action.

The agent follows a bounded execution loop:

1. Wakes autonomously

Google Cloud Scheduler periodically triggers the ApprovalLoop backend.

No user message is required to start the workflow.

2. Observes workflow state

The backend reads open expense approvals from Firestore and determines which reports are still waiting for action.

3. Makes a bounded decision

Eligibility is determined by deterministic workflow rules rather than by the LLM.

For the demo:

  • Pending for more than 30 seconds → Nudge
  • Nudged for more than 90 seconds → Escalate

Production defaults use longer windows:

  • Pending for more than 24 hours → Nudge
  • Nudged for more than 72 hours → Escalate

4. Discovers the procedural skill

The reusable approval_escalation skill is loaded at runtime through SkillRegistry.

High-value escalation scenarios can additionally load the skill's Level-2 reference material.

5. Claims the action atomically

Before generating or sending a notification, ApprovalLoop claims the logical action using:

{report_id}:{action_type}

The claim is transactional, preventing duplicate logical actions across repeated scheduler ticks or overlapping processing.

6. Generates contextual language

Google Gemini generates the natural-language wording for the notification through the Google GenAI SDK.

The model is used for communication, not enterprise authority.

7. Validates deterministically

The generated notification is checked against authoritative workflow data.

The four-point safety validator verifies:

  • Authorized recipient
  • Exact report ID
  • Exact monetary amount
  • Legal state transition

8. Enforces deterministic policy

Python policy code remains authoritative over:

  • Eligibility
  • Recipient restrictions
  • Financial authorization
  • State invariants
  • Environment restrictions
  • High-value escalation rules

For high-value expenses, the system requires an appropriate senior/admin recipient.

9. Dispatches safely

Authorized notifications are passed through a deterministic notification-provider interface.

The demo uses a simulated notification provider with:

  • Provider-side idempotency
  • Delivery receipts
  • Deterministic behavior

Slack and SMTP adapters are also implemented.

10. Protects human actions

Autonomous processing can race with human activity.

For example, an agent may begin preparing an escalation while an administrator resolves the report.

ApprovalLoop uses conditional state transitions so stale autonomous work cannot overwrite a newer human decision.

11. Records execution

Execution tracing captures the workflow path, while the AgBOM exposes declared runtime dependencies and safety information.


The Core Idea: LLM Proposes. Code Disposes.

The most important architectural boundary in ApprovalLoop is:

LLM proposes. Code disposes.

Gemini generates communication.

It does not control:

  • Who receives the notification
  • What amount is authoritative
  • Whether an approval is eligible
  • Whether a financial action is authorized
  • Whether workflow state can change
  • Whether a notification can be dispatched

Those decisions remain under deterministic application code and transactional infrastructure.

This allows the system to benefit from an LLM's language capabilities without allowing the model to become the source of truth for sensitive enterprise operations.


How We Built It

AI & Agent Layer

  • Google Gemini 3.7 Flash
  • Google GenAI SDK (google-genai)
  • Reusable approval_escalation procedural skill
  • Progressive disclosure through SkillRegistry

The LLM is intentionally restricted to natural-language generation.

Backend

  • FastAPI
  • Python 3.10+
  • Pydantic v2
  • Python Decimal for monetary precision
  • Deterministic eligibility engine
  • Deterministic policy engine
  • Four-point safety validator
  • Transactional state management
  • Conditional state transitions
  • OpenTelemetry-compatible execution tracing

Frontend

  • React 18
  • TypeScript
  • Vite
  • Tailwind CSS
  • Lucide Icons

The dashboard is intentionally observational.

The user does not have to click a button to tell the agent what to do. The purpose of the dashboard is to observe what the autonomous system is doing.

Google Cloud

  • Cloud Run — serverless backend execution
  • Cloud Scheduler — autonomous time-based triggering
  • Firestore — workflow state, reports, action claims, registry and durable state
  • Secret Manager — supported for production secret injection

The production deployment configures Cloud Scheduler with a one-minute cadence.

Additional Safety

The project also supports optional Google Cloud Model Armor inspection of model inputs and outputs when configured.

The core approval workflow does not depend on the model being trusted with business authority: deterministic validation and policy enforcement remain the final gates.


Demo Configuration

The demo uses intentionally short thresholds so the autonomous behavior can be observed quickly.

Setting Demo
Nudge threshold 30 seconds
Escalation threshold 90 seconds after nudge
Demo tick cadence 15 seconds

Production defaults:

Setting Production
Nudge threshold 24 hours
Escalation threshold 72 hours
Scheduler cadence 1 minute

This allows the same architecture to demonstrate autonomous behavior quickly while retaining realistic production-oriented defaults.


Architecture

                 Google Cloud Scheduler
                         │
                         │ recurring /api/tick
                         ▼
                  Cloud Run / FastAPI
                         │
                         ▼
                Observe Open Approvals
                         │
                         ▼
             Deterministic Eligibility
              (clock + workflow state)
                         │
                         ▼
              Load approval_escalation
                    procedural skill
                         │
                         ▼
                Atomic Outbox Claim
             {report_id}:{action_type}
                         │
                         ▼
                Gemini Wording Draft
                         │
                         ▼
             Deterministic Safety Gate
          recipient / ID / amount / state
                         │
                         ▼
                Deterministic Policy
                         │
                  ┌──────┴──────┐
                  │             │
                BLOCK         ALLOW
                  │             │
                  ▼             ▼
                Audit      Notification Worker
                                │
                                ▼
                     Conditional State Transition
                                │
                                ▼
                       Firestore + Trace

Challenges We Faced

The hardest part wasn't getting an LLM to generate a reminder.

The real challenge was:

How do you give an AI agent autonomy without giving the language model authority over sensitive enterprise actions?

A naïve implementation could simply ask an LLM:

"This approval is old. What should I do?"

But that would allow the model to influence business-critical decisions.

We instead established a strict architectural boundary:

LLM proposes. Code disposes.

The model can propose language.

Deterministic code decides whether the action is allowed.

That separation required us to build several safeguards around the model.

Deterministic eligibility

The clock and workflow state—not the LLM—determine whether a nudge or escalation is due.

Transactional action claims

Repeated scheduler ticks must not produce duplicate actions.

The {report_id}:{action_type} key provides an idempotent boundary around each logical action.

Deterministic validation

The generated message is checked against authoritative data before dispatch.

Policy enforcement

Even a perfectly written LLM response cannot bypass authorization or financial policy.

Race-condition protection

The hardest edge case was concurrent human activity.

A human may resolve an approval while the autonomous agent is processing it.

ApprovalLoop therefore checks state before dispatch and performs a conditional state transition at commit time.

If the workflow has changed, the autonomous action becomes stale and is skipped instead of overwriting the human decision.


Accomplishments We're Proud Of

128 Backend Test Functions

The repository contains 128 backend test functions covering areas including:

  • Safety validation
  • Policy enforcement
  • State transitions
  • Concurrency behavior
  • Runtime behavior
  • API behavior
  • Agent behavior
  • Integration behavior

1,000-Report Deterministic Benchmark

We also executed a deterministic synthetic workload containing 1,000 approval reports.

Observed local run:

  • 1,000 synthetic reports
  • 350 autonomous nudge actions
  • 250 autonomous escalation actions
  • 50 admin fallback escalations
  • 50 race-condition guards triggered
  • 0 duplicate actions on repeated ticks
  • 0 invalid state transitions
  • 0 unauthorized sends observed
  • 0 human prompts required
  • 0.87 seconds total local runtime

The benchmark is intentionally synthetic and deterministic.

Its purpose is to validate workflow invariants and safety behavior—not to claim production throughput or distributed concurrency performance.


What We Learned

1. The Clock Can Be an Agent Trigger

Many agentic systems begin with a user message.

ApprovalLoop begins with something different:

the passage of time.

For workflows where inaction itself is meaningful, time can become an authoritative trigger.

That opens a broader class of autonomous systems where agents respond not only to what users say, but also to what users haven't done yet.

2. LLMs Should Not Own Enterprise Authority

Our most important architectural lesson was:

LLM proposes. Code disposes.

Natural-language generation and authorization are fundamentally different responsibilities.

The model is useful precisely because it doesn't need to own the business decision.

3. Race Conditions Are First-Class Problems

An autonomous system operates in an environment that can change while it is processing.

Humans can approve, reject, cancel, or modify a workflow at any time.

Therefore, autonomous state transitions cannot simply assume that the world is unchanged.

Conditional transitions are essential.

4. Autonomy Requires Observability

When a system can act without a human prompt, developers need to understand exactly what happened.

ApprovalLoop therefore captures information about:

  • What triggered the execution
  • What the agent observed
  • Which action became eligible
  • Which procedural skill was loaded
  • What wording was generated
  • Which validations ran
  • What policy decision was made
  • Whether dispatch succeeded
  • Whether the final state transition succeeded or was skipped

Autonomy without observability would be difficult to trust or debug.


What's Next

The current implementation demonstrates the autonomous decision-and-action loop in a controlled environment.

Our next step is to move the architecture toward production enterprise workflows.

Real notification integrations

Expand beyond the deterministic demo provider into real:

  • Email
  • Slack
  • Microsoft Teams
  • Enterprise workflow systems

Configurable enterprise policies

Allow organizations to configure:

  • Approval thresholds
  • Escalation windows
  • Financial limits
  • Recipient rules
  • Organizational approval hierarchies

Production observability

Integrate the execution traces with production OpenTelemetry infrastructure and enterprise observability platforms.

Distributed concurrency testing

Move from deterministic local simulation to true distributed-load testing across multiple workers and scheduler invocations.

Human override and audit controls

Provide explicit controls for reviewing, overriding, and auditing autonomous actions in sensitive workflows.

More procedural skills

Extend the same architecture beyond expense approvals to:

  • Purchase orders
  • IT access requests
  • Compliance reviews
  • Procurement workflows
  • Other time-sensitive enterprise processes

Our Long-Term Goal

ApprovalLoop is based on a simple idea:

The next generation of agents shouldn't only respond to what humans ask. They should understand when the absence of action itself requires a response.

Our goal is to build agents that don't just answer when asked—

but safely act when the workflow requires action.

Built With

Share this project:

Updates

Submission history