# My CoWork Agent Burned Through $800 in Credits Before Anyone Noticed

> Source: <https://pub.towardsai.net/my-cowork-agent-burned-through-800-in-credits-before-anyone-noticed-56e15319f6c3?source=rss----98111c9905da---4>
> Published: 2026-07-11 09:28:53+00:00

It happened on a Friday afternoon. A data scientist on my team was testing a CoWork agent with broad tool access — three semantic views, two Cortex Search services, and an experimental SQL execution tool. The agent entered a reasoning loop: queried, evaluated, decided it needed more context, queried again with a broader filter, still wasn’t satisfied, repeated for 47 minutes.

The compute bill for that single session: $800. The agent was doing exactly what it was configured to do. We just hadn’t configured limits on *how long* it could do it.

Summit 2025 Context:Snowflake positions CoWork as the control plane connecting data, context, and enterprise systems to drive action. Christian Kleinerman (EVP Product): “CoWork gives every employee a personal agent… all within a secure, governed environment they trust.”

Admin-defined policies ensure autonomous actions stay within boundaries: “Admins will decide what an agent does on its own, what needs sign-off, and what it cannot use, with every action logged with its policy reason.”

TheNatoma acquisitionadds enterprise MCP governance: secure connectivity, identity-aware authorization, and auditability for agents operating across enterprise systems.

Reference:https://www.snowflake.com/en/blog/snowflake-cowork-personal-work-agent/

Every CoWork interaction runs under the user’s **default role** (not the active session role). Object grants, row access policies, masking — all apply. The agent has no elevated privileges.

Where teams stumble: the agent needs grants on *tools*, not just data. The user’s default role must be granted USAGE on the database, schema, and agent itself (per official docs). Here’s the correct privilege set:

```
-- ═══════════════════════════════════════════════════════════════════════-- COWORK AGENT RBAC — PRODUCTION TEMPLATE-- ═══════════════════════════════════════════════════════════════════════CREATE ROLE IF NOT EXISTS finance_agent_user;-- Data access (underlying tables the semantic view references)GRANT USAGE ON DATABASE analytics TO ROLE finance_agent_user;GRANT USAGE ON SCHEMA analytics.finance TO ROLE finance_agent_user;GRANT SELECT ON ALL TABLES IN SCHEMA analytics.finance  TO ROLE finance_agent_user;GRANT SELECT ON FUTURE TABLES IN SCHEMA analytics.finance  TO ROLE finance_agent_user;-- Semantic view: USAGE on database + schema, then SELECT on the view-- (The privilege for semantic views is SELECT, not USAGE)GRANT USAGE ON DATABASE cortex_ai TO ROLE finance_agent_user;GRANT USAGE ON SCHEMA cortex_ai.semantic_views TO ROLE finance_agent_user;GRANT SELECT ON SEMANTIC VIEW  cortex_ai.semantic_views.finance_revenue  TO ROLE finance_agent_user;-- Cortex Search service: USAGE on database, schema, and serviceGRANT USAGE ON SCHEMA cortex_ai.search_services TO ROLE finance_agent_user;GRANT USAGE ON CORTEX SEARCH SERVICE  cortex_ai.search_services.finance_policies  TO ROLE finance_agent_user;-- Agent: USAGE (object type keyword is AGENT, not CORTEX AGENT)GRANT USAGE ON SCHEMA cortex_ai.agents TO ROLE finance_agent_user;GRANT USAGE ON AGENT cortex_ai.agents.finance_agent  TO ROLE finance_agent_user;-- Cortex AI platform access (required for AI function calls)GRANT DATABASE ROLE SNOWFLAKE.CORTEX_USER TO ROLE finance_agent_user;-- Warehouse for computeGRANT USAGE ON WAREHOUSE cowork_finance_wh TO ROLE finance_agent_user;-- Assign to business rolesGRANT ROLE finance_agent_user TO ROLE finance_analyst;GRANT ROLE finance_agent_user TO ROLE finance_manager;
-- ═══════════════════════════════════════════════════════════════════════-- PRIVILEGE QUICK REFERENCE-- ═══════════════════════════════════════════════════════════════════════-- | Object Type           | Correct Privilege | Common Mistake          |-- |-----------------------|-------------------|-------------------------|-- | Semantic View         | SELECT            | USAGE (invalid)         |-- | Cortex Search Service | USAGE             | SELECT                  |-- | Agent                 | USAGE             | CORTEX AGENT keyword    |-- | Agent (create)        | CREATE AGENT      | (on schema)             |-- | Agent (update)        | MODIFY            | (on agent object)       |-- | Agent (view threads)  | MONITOR           | (on agent object)       |-- | Tables (underlying)   | SELECT            | Forgetting these        |-- ═══════════════════════════════════════════════════════════════════════
-- ═══════════════════════════════════════════════════════════════════════-- RESTRICTING ACCESS: CORTEX_AGENT_USER vs CORTEX_USER-- ═══════════════════════════════════════════════════════════════════════-- CORTEX_USER grants access to ALL Cortex features (AI functions, agents,-- search, analyst, etc.). For users who should ONLY access agents:USE ROLE ACCOUNTADMIN;CREATE ROLE IF NOT EXISTS agent_only_role;GRANT DATABASE ROLE SNOWFLAKE.CORTEX_AGENT_USER TO ROLE agent_only_role;GRANT ROLE agent_only_role TO USER example_user;-- To enforce this restriction, revoke CORTEX_USER from roles that-- shouldn't have broad Cortex access:-- REVOKE DATABASE ROLE SNOWFLAKE.CORTEX_USER FROM ROLE analyst_role;
-- ═══════════════════════════════════════════════════════════════════════-- PER-FUNCTION AI ACCESS CONTROL (GA)-- ═══════════════════════════════════════════════════════════════════════-- Control which AI functions specific roles can call. Useful when agents-- should only use certain functions (e.g., AI_COMPLETE but not AI_EXTRACT).USE ROLE ACCOUNTADMIN;-- Remove blanket AI function access from PUBLICREVOKE USE AI FUNCTIONS ON ACCOUNT FROM ROLE PUBLIC;-- Grant only specific functions to the agent roleGRANT USE AI FUNCTION AI_COMPLETE ON ACCOUNT TO ROLE finance_agent_user;GRANT USE AI FUNCTION AI_CLASSIFY ON ACCOUNT TO ROLE finance_agent_user;GRANT USE AI FUNCTION AI_EXTRACT ON ACCOUNT TO ROLE finance_agent_user;-- The role still needs CORTEX_USER or AI_FUNCTIONS_USER database role-- (already granted above via SNOWFLAKE.CORTEX_USER)-- Verify grants:SHOW GRANTS TO ROLE finance_agent_user;
-- ═══════════════════════════════════════════════════════════════════════-- MODEL-LEVEL ACCESS CONTROL (GA)-- ═══════════════════════════════════════════════════════════════════════-- Restrict which LLM models a role can invoke. Prevents agents from-- accidentally using expensive models.USE ROLE ACCOUNTADMIN;-- Option A: Account-level allowlist (simple, broad)ALTER ACCOUNT SET CORTEX_MODELS_ALLOWLIST = 'mistral-large2,llama3.1-70b';-- Option B: Role-based model access (fine-grained)-- First, populate model objects:CALL SNOWFLAKE.MODELS.CORTEX_BASE_MODELS_REFRESH();-- Grant specific model access to the agent role:GRANT APPLICATION ROLE SNOWFLAKE."CORTEX-MODEL-ROLE-LLAMA3.1-70B"  TO ROLE finance_agent_user;-- To use RBAC exclusively, block the allowlist:-- ALTER ACCOUNT SET CORTEX_MODELS_ALLOWLIST = 'None';
```

Test with end-user roles. Never ACCOUNTADMIN. ACCOUNTADMIN masks every privilege gap because it inherits all grants.

The Summit announcement introduces a governance framework specifically for autonomous agent actions. Three tiers:

Every action is logged with its policy reason. This is the “why was this allowed/blocked” audit trail that enterprise security teams demand.

For proactive agents (automations/subscriptions), this framework becomes essential. An agent running a Monday morning check autonomously needs clear boundaries:

Resource monitors cap credit consumption at the warehouse level. They work for CoWork the same way they work for any warehouse-bound compute:

```
CREATE RESOURCE MONITOR cowork_finance_monitor  WITH CREDIT_QUOTA = 50  FREQUENCY = DAILY  START_TIMESTAMP = IMMEDIATELY  TRIGGERS    ON 75 PERCENT DO NOTIFY    ON 90 PERCENT DO SUSPEND    ON 100 PERCENT DO SUSPEND_IMMEDIATE;ALTER WAREHOUSE cowork_finance_wh  SET RESOURCE_MONITOR = cowork_finance_monitor;
```

Why this isn’t sufficient alone: my $800 incident happened in 47 minutes — well within a reasonable daily budget. Resource monitors catch sustained overspend but not single-session spikes. They don’t give you per-session limits, rate-of-consumption alerting, or agent-specific attribution.

Also: resource monitors apply to warehouse compute credits only. Cortex AI token costs (from AI_COMPLETE, AI_EXTRACT, etc.) are serverless and NOT captured by resource monitors. You need CORTEX_AI_FUNCTIONS_USAGE_HISTORY for those.

```
-- Layer 1 — Warehouse sizing and auto-suspend:CREATE WAREHOUSE IF NOT EXISTS cowork_finance_wh  WAREHOUSE_SIZE = 'XSMALL'  AUTO_SUSPEND = 60  AUTO_RESUME = TRUE  INITIALLY_SUSPENDED = TRUE  STATEMENT_TIMEOUT_IN_SECONDS = 120  STATEMENT_QUEUED_TIMEOUT_IN_SECONDS = 60;
```

**Layer 2 — Statement timeouts (120s):** Kills runaway queries per iteration. Even if the agent loops 20 times, each step is bounded.

```
-- Layer 3 — Governance tags for attribution:CREATE TAG IF NOT EXISTS cortex_ai.tags.agent_name  ALLOWED_VALUES 'finance_agent', 'sales_agent', 'operations_agent';CREATE TAG IF NOT EXISTS cortex_ai.tags.team  ALLOWED_VALUES 'finance', 'sales', 'operations', 'data_platform';CREATE TAG IF NOT EXISTS cortex_ai.tags.cost_center  COMMENT = 'Maps agent compute to internal cost centers';ALTER WAREHOUSE cowork_finance_wh SET TAG  cortex_ai.tags.agent_name = 'finance_agent',  cortex_ai.tags.team = 'finance',  cortex_ai.tags.cost_center = 'CC-4200';
```

**Layer 4 — Resource monitors** as daily backstop (see above).

**Layer 5 — Resource budgets** for agent-specific monthly limits. Resource budgets (GA for Cortex Agents and CoWork) let you define monthly credit limits on tagged agent objects with automated actions when thresholds are reached. Budget evaluation runs periodically (up to 8 hours standard, or 2 hours with latency-optimized option).

CORTEX_AI_FUNCTIONS_USAGE_HISTORY tracks token-level consumption for all Cortex AI Functions (AI_COMPLETE, AI_EXTRACT, etc.). Latency: up to 10 minutes.

```
-- Daily credit consumption by function and model:SELECT    DATE_TRUNC('day', START_TIME) AS usage_date,    FUNCTION_NAME,    MODEL_NAME,    SUM(CREDITS) AS total_credits,    COUNT(DISTINCT QUERY_ID) AS query_countFROM SNOWFLAKE.ACCOUNT_USAGE.CORTEX_AI_FUNCTIONS_USAGE_HISTORYWHERE START_TIME >= DATEADD('day', -30, CURRENT_TIMESTAMP())GROUP BY 1, 2, 3ORDER BY usage_date DESC, total_credits DESC;
-- Monthly credit consumption by user (identify top consumers):-- NOTE: USER_ID in CORTEX_AI_FUNCTIONS_USAGE_HISTORY is VARCHAR.-- Join to USERS view requires TO_VARCHAR() cast on USERS.USER_ID.SELECT    DATE_TRUNC('month', h.START_TIME) AS usage_month,    u.NAME AS user_name,    u.LOGIN_NAME,    SUM(h.CREDITS) AS total_credits,    COUNT(DISTINCT h.QUERY_ID) AS query_countFROM SNOWFLAKE.ACCOUNT_USAGE.CORTEX_AI_FUNCTIONS_USAGE_HISTORY hLEFT JOIN SNOWFLAKE.ACCOUNT_USAGE.USERS u    ON h.USER_ID = TO_VARCHAR(u.USER_ID)WHERE h.START_TIME >= DATEADD('month', -3, CURRENT_TIMESTAMP())  AND u.DELETED_ON IS NULLGROUP BY 1, 2, 3ORDER BY usage_month DESC, total_credits DESC;
-- ═══════════════════════════════════════════════════════════════════════-- AGENT-SPECIFIC COST TRACKING (using CORTEX_AGENT_USAGE_HISTORY)-- ═══════════════════════════════════════════════════════════════════════-- Verified columns: START_TIME, END_TIME, USER_ID, USER_NAME,-- REQUEST_ID, PARENT_REQUEST_ID, AGENT_DATABASE_NAME, AGENT_SCHEMA_NAME,-- AGENT_NAME, TOKEN_CREDITS, TOKENS, TOKENS_GRANULAR, CREDITS_GRANULAR,-- METADATA---- NOTE: There are NO columns named CREDITS, INPUT_TOKENS, or OUTPUT_TOKENS.-- Use TOKEN_CREDITS for cost, TOKENS for total count.-- Token breakdown (input/output) lives in TOKENS_GRANULAR (ARRAY).SELECT    DATE_TRUNC('day', START_TIME) AS usage_date,    AGENT_NAME,    AGENT_DATABASE_NAME || '.' || AGENT_SCHEMA_NAME AS agent_location,    SUM(TOKEN_CREDITS) AS total_token_credits,    SUM(TOKENS) AS total_tokens,    ROUND(AVG(TIMESTAMPDIFF('second', START_TIME, END_TIME)), 1)        AS avg_duration_seconds,    COUNT(*) AS invocation_count,    COUNT(DISTINCT USER_NAME) AS unique_usersFROM SNOWFLAKE.ACCOUNT_USAGE.CORTEX_AGENT_USAGE_HISTORYWHERE START_TIME >= DATEADD('day', -7, CURRENT_TIMESTAMP())GROUP BY 1, 2, 3ORDER BY total_token_credits DESC;
```

Per official docs: “If a request starts in Snowflake CoWork and invokes a Cortex Agent, that usage is attributed to Snowflake CoWork.” Agent-scoped resource budgets do NOT capture CoWork-initiated requests. You need BOTH an agent budget AND a CoWork budget for full coverage.

```
-- CoWork usage (includes agent calls made through CoWork UI):SELECT    DATE_TRUNC('day', START_TIME) AS usage_date,    USER_NAME,    SUM(TOKEN_CREDITS) AS total_token_credits,    SUM(TOKENS) AS total_tokens,    COUNT(*) AS request_countFROM SNOWFLAKE.ACCOUNT_USAGE.SNOWFLAKE_INTELLIGENCE_USAGE_HISTORYWHERE START_TIME >= DATEADD('day', -7, CURRENT_TIMESTAMP())GROUP BY 1, 2ORDER BY total_token_credits DESC;
-- Weekly reporting by tagged agent warehouse:WITH tagged_warehouses AS (  SELECT object_name AS warehouse_name, tag_value AS agent_name  FROM snowflake.account_usage.tag_references  WHERE tag_name = 'AGENT_NAME' AND domain = 'WAREHOUSE')SELECT  DATE_TRUNC('week', wmh.start_time) AS week_start,  tw.agent_name,  ROUND(SUM(wmh.credits_used), 2) AS total_credits,  ROUND(SUM(wmh.credits_used) * 3.00, 2) AS estimated_cost_usdFROM snowflake.account_usage.warehouse_metering_history wmhJOIN tagged_warehouses tw  ON UPPER(wmh.warehouse_name) = UPPER(tw.warehouse_name)WHERE wmh.start_time >= DATEADD(week, -4, CURRENT_TIMESTAMP())GROUP BY 1, 2ORDER BY 1 DESC, total_credits DESC;
```

From official Snowflake docs — monitors total monthly AI function spend and sends email when threshold exceeded.

```
CREATE OR REPLACE NOTIFICATION INTEGRATION ai_cost_alerts    TYPE = EMAIL    ENABLED = TRUE    ALLOWED_RECIPIENTS = ('admin@company.com', 'finops@company.com');-- Track alert state to prevent duplicate notifications per month:CREATE TABLE IF NOT EXISTS cortex_ai.monitoring.ai_functions_alert_state (    ALERT_NAME VARCHAR NOT NULL,    ALERT_MONTH DATE NOT NULL,    SENT_AT TIMESTAMP_LTZ DEFAULT CURRENT_TIMESTAMP(),    CREDITS_AT_ALERT NUMBER(38,6),    PRIMARY KEY (ALERT_NAME, ALERT_MONTH));-- Alert that fires when monthly AI function spend exceeds threshold:CREATE OR REPLACE ALERT cortex_ai.monitoring.ai_functions_monthly_spend_alert    WAREHOUSE = cowork_finance_wh    SCHEDULE = 'USING CRON 0 * * * * UTC'    IF (EXISTS (        SELECT 1        FROM SNOWFLAKE.ACCOUNT_USAGE.CORTEX_AI_FUNCTIONS_USAGE_HISTORY        WHERE START_TIME >= DATE_TRUNC('month', CURRENT_TIMESTAMP())        HAVING SUM(CREDITS) > 1000  -- adjust threshold    ))    THEN        CALL SYSTEM$SEND_EMAIL(            'ai_cost_alerts',            'admin@company.com',            'AI Functions Monthly Spend Alert',            'Monthly AI Function credit consumption has exceeded 1000 credits. Please review usage.'        );ALTER ALERT cortex_ai.monitoring.ai_functions_monthly_spend_alert RESUME;
-- ═══════════════════════════════════════════════════════════════════════-- AUTONOMOUS AGENT COST ALERT-- ═══════════════════════════════════════════════════════════════════════-- For proactive agents (automations/subscriptions) that run without-- interactive sessions. Monitors warehouse-level compute spikes.CREATE OR REPLACE ALERT cortex_ai.monitoring.autonomous_agent_cost_alert  WAREHOUSE = cowork_finance_wh  SCHEDULE = '5 MINUTE'  IF (EXISTS (    SELECT 1    FROM snowflake.account_usage.warehouse_metering_history    WHERE start_time >= DATEADD(hour, -1, CURRENT_TIMESTAMP())      AND warehouse_name LIKE 'COWORK_%_WH'    GROUP BY warehouse_name    HAVING SUM(credits_used) > 10  ))  THEN    CALL SYSTEM$SEND_EMAIL(      'ai_cost_alerts',      'platform-team@company.com',      'ALERT: Autonomous Agent High Cost',      'An agent consumed >10 credits in the last hour without interactive session.'    );ALTER ALERT cortex_ai.monitoring.autonomous_agent_cost_alert RESUME;
```

From the official docs pattern — enforces per-user monthly credit caps on AI function usage by revoking the AI_FUNCTIONS_USER_ROLE when limits are exceeded. A monthly task restores access at the start of each billing period.

Prerequisites (run as ACCOUNTADMIN):

See: [https://docs.snowflake.com/en/user-guide/snowflake-cortex/ai-func-cost-management](https://docs.snowflake.com/en/user-guide/snowflake-cortex/ai-func-cost-management) for the full implementation with stored procedures.

Detects AI function queries exceeding a credit threshold and cancels them. Uses IS_COMPLETED = FALSE to identify still-running queries. Note: cancelled queries still incur charges for credits consumed prior to cancellation.

Key insight from docs: CORTEX_AI_FUNCTIONS_USAGE_HISTORY splits usage into one-hour windows, so a long-running query produces multiple rows. Aggregate by QUERY_ID and check BOOLOR_AGG(IS_COMPLETED) = FALSE to find still-running queries.

```
-- Detect runaway queries (still running, exceeding credit threshold):SELECT    QUERY_ID,    USER_ID,    FUNCTION_NAME,    MODEL_NAME,    MIN(START_TIME) AS first_window,    MAX(END_TIME) AS latest_window,    TIMESTAMPDIFF('minute', MIN(START_TIME), CURRENT_TIMESTAMP())        AS running_minutes,    ROUND(SUM(CREDITS), 4) AS credits_consumed_so_far,    BOOLOR_AGG(IS_COMPLETED) AS is_completedFROM SNOWFLAKE.ACCOUNT_USAGE.CORTEX_AI_FUNCTIONS_USAGE_HISTORYWHERE START_TIME >= DATEADD('hour', -6, CURRENT_TIMESTAMP())GROUP BY 1, 2, 3, 4HAVING BOOLOR_AGG(IS_COMPLETED) = FALSE   AND SUM(CREDITS) > 2ORDER BY credits_consumed_so_far DESC;
-- Automated cancellation procedure:CREATE OR REPLACE PROCEDURE cortex_ai.monitoring.cancel_runaway_ai_queries(    credit_threshold NUMBER DEFAULT 5,    lookback_hours NUMBER DEFAULT 4)RETURNS TABLE(query_id VARCHAR, credits NUMBER, action VARCHAR)LANGUAGE SQLASBEGIN    LET res RESULTSET := (        WITH runaway_queries AS (            SELECT                QUERY_ID,                ROUND(SUM(CREDITS), 4) AS total_credits            FROM SNOWFLAKE.ACCOUNT_USAGE.CORTEX_AI_FUNCTIONS_USAGE_HISTORY            WHERE START_TIME >= DATEADD('hour', -:lookback_hours, CURRENT_TIMESTAMP())            GROUP BY 1            HAVING BOOLOR_AGG(IS_COMPLETED) = FALSE               AND SUM(CREDITS) > :credit_threshold        )        SELECT            QUERY_ID,            total_credits AS credits,            'DETECTED' AS action        FROM runaway_queries    );    RETURN TABLE(res);END;-- Schedule runaway detection every 10 minutes:CREATE OR REPLACE TASK cortex_ai.monitoring.runaway_detection_task  WAREHOUSE = cowork_finance_wh  SCHEDULE = '10 MINUTE'AS  CALL cortex_ai.monitoring.cancel_runaway_ai_queries(5, 4);
```

See: [https://docs.snowflake.com/en/user-guide/snowflake-cortex/ai-func-cost-management](https://docs.snowflake.com/en/user-guide/snowflake-cortex/ai-func-cost-management)

Official pattern using SNOWFLAKE.CORE.BUDGET class. Budget enforcement: up to 8 hours standard, 2 hours low-latency.

```
-- Step 1: Tag the agent for budget associationALTER AGENT cortex_ai.agents.finance_agent  SET TAG cortex_ai.tags.cost_center = 'CC-4200';-- Step 2: Create budget instanceUSE SCHEMA cortex_ai.monitoring;CREATE SNOWFLAKE.CORE.BUDGET IF NOT EXISTS agent_finance_budget();-- Step 3: Set monthly spending limit (credits)CALL agent_finance_budget!SET_SPENDING_LIMIT(500);-- Step 4: Associate tag with budgetCALL agent_finance_budget!SET_RESOURCE_TAGS(  [    [(SELECT SYSTEM$REFERENCE('TAG',       'cortex_ai.tags.cost_center',       'SESSION',       'applybudget')),     'CC-4200']  ],  'UNION');-- Step 5: Email notification at 80%CALL agent_finance_budget!SET_EMAIL_NOTIFICATIONS(  'ai_cost_alerts',  'finops@company.com');CALL agent_finance_budget!SET_NOTIFICATION_THRESHOLD(80);-- Step 6: Check budget usageCALL agent_finance_budget!GET_SERVICE_TYPE_USAGE_V2(  DATE_TRUNC('month', CURRENT_DATE())::VARCHAR,  CURRENT_DATE()::VARCHAR);
```

Cortex AI Guardrails detect prompt injection and jailbreak attempts. Essential for production agent deployments.

```
-- Enable guardrails (account-level, run once):ALTER ACCOUNT SET AI_SETTINGS = $$  guardrails:    advanced_prompt_injection:      - enabled: true$$;-- Monitor flagged requests (potential attacks):SELECT    USAGE_TIME,    USER_NAME,    AGENTIC_SOURCE,    REQUEST_ID,    GUARDRAILS_SIGNAL,    GUARDRAIL_RESULTSFROM SNOWFLAKE.ACCOUNT_USAGE.CORTEX_AI_GUARDRAILS_USAGE_HISTORYWHERE GUARDRAILS_SIGNAL = TRUE  AND USAGE_TIME >= DATEADD('hour', -72, CURRENT_TIMESTAMP())ORDER BY USAGE_TIME DESCLIMIT 50;-- Guardrails alert (fires on prompt injection detection):CREATE OR REPLACE ALERT cortex_ai.monitoring.guardrails_flag_alert  WAREHOUSE = cowork_finance_wh  SCHEDULE = '15 MINUTE'  IF (EXISTS (    SELECT 1    FROM SNOWFLAKE.ACCOUNT_USAGE.CORTEX_AI_GUARDRAILS_USAGE_HISTORY    WHERE GUARDRAILS_SIGNAL = TRUE      AND USAGE_TIME >= DATEADD('minute', -15, CURRENT_TIMESTAMP())  ))  THEN    CALL SYSTEM$SEND_EMAIL(      'ai_cost_alerts',      'platform-team@company.com',      'SECURITY: Guardrails Flagged Prompt Injection',      'Cortex AI Guardrails detected a possible prompt injection in the last 15 minutes.'    );ALTER ALERT cortex_ai.monitoring.guardrails_flag_alert RESUME;
| View                                        | Tracks                     || ------------------------------------------- | -------------------------- || CORTEX_AGENT_USAGE_HISTORY                  | Agent token/tool usage     || CORTEX_AI_FUNCTIONS_USAGE_HISTORY           | AI function tokens/credits || CORTEX_CODE_CLI_USAGE_HISTORY               | Cortex Code CLI            || CORTEX_CODE_SNOWSIGHT_USAGE_HISTORY         | Cortex Code in Snowsight   || CORTEX_ANALYST_USAGE_HISTORY                | Cortex Analyst messages    || CORTEX_FINE_TUNING_USAGE_HISTORY            | Fine-tuning time           || CORTEX_PROVISIONED_THROUGHPUT_USAGE_HISTORY | PTU hours                  || CORTEX_SEARCH_DAILY_USAGE_HISTORY           | Search serving + tokens    || SNOWFLAKE_INTELLIGENCE_USAGE_HISTORY        | CoWork/Intelligence tokens || CORTEX_REST_API_USAGE_HISTORY               | REST API tokens (currency) || CORTEX_AI_GUARDRAILS_USAGE_HISTORY          | Guardrails tokens          |
| Feature                  | Budget Type                            || ------------------------ | -------------------------------------- || Cortex Agents            | Resource budgets, shared resource      || Cortex AI Functions      | Shared resource budgets                || Cortex Code CLI          | Shared resource budgets, credit limits || Cortex Code in Snowsight | Shared resource budgets, credit limits || Snowflake CoWork         | Resource budgets, shared resource      || Cortex Search            | Planned (not yet available)            || Cortex Analyst           | Not supported nor planned              || Cortex Fine-tuning       | Not supported nor planned              |
```

Budget enforcement timing: actions can take up to 8 hours under normal operation, or up to 2 hours with latency-optimized option. Budgets support stored procedure triggers at percentage thresholds.

**The surprise:** Statement timeouts (Layer 2) are more effective than resource monitors for controlling agent costs in real-time. Capping per-query execution at 120s prevents worst-case scenarios entirely — even if the agent loops 20 times, total compute is bounded.

**The limitation the docs don’t make obvious:** Three latency gaps stack: CORTEX_AI_FUNCTIONS_USAGE_HISTORY has up to 10 minutes latency. Budget evaluation adds 2–8 hours on top. Tag changes reflected in budgets can take another 8 hours. Combined, there’s a meaningful window between an agent overspending and any automated response.

**The other limitation:** Agent budgets and CoWork budgets are separate scopes. A request entering through CoWork that calls your agent is attributed to CoWork, not the agent. If you only budget the agent, CoWork usage flies under the radar. Budget both.

**My recommendation:** One X-Small warehouse per agent domain. Don’t share with analytics workloads. Agents are bursty and iterative; shared warehouses make attribution impossible and risk loops affecting scheduled jobs. Pair with CORTEX_AGENT_USAGE_HISTORY (TOKEN_CREDITS column, not CREDITS) and SNOWFLAKE_INTELLIGENCE_USAGE_HISTORY together for complete coverage across direct agent and CoWork-initiated calls.

Governing CoWork requires solving two problems: data access (existing RBAC with correct privilege types — USAGE on semantic views, search services, and agents) and compute consumption (layered cost controls across warehouse and serverless dimensions). Resource budgets and CORTEX_AI_FUNCTIONS_USAGE_HISTORY close the serverless visibility gap, but budget enforcement latency (2–8 hours) means statement timeouts remain your fastest line of defense.

Admin-defined policies add a third dimension: action governance — what agents do autonomously vs. what needs human sign-off. With proactive agents coming, this three-dimensional governance model (access + compute + action) becomes non-negotiable for enterprise deployment.

Next: **Article 5 — CoWork in Production: Monitoring, Troubleshooting, and Performance Patterns.**

*Deployment Code:** The complete SQL scripts, stored procedures, and task definitions from this article are available on GitHub.*

If this was useful — give it a clap 👏, share it with someone building on Snowflake, and subscribe to [Snowflake Chronicles](https://medium.com/@snowflakechronicles) so you don’t miss the next one. Every piece is practitioner-first and production-focused. Let’s connect on [LinkedIn](https://linkedin.com/in/satishkumar-snowflake).

*Disclaimer: All views expressed are my own and do not reflect those of any current or former employer.*

#SnowflakeChronicles #Snowflake #AIGovernance #CortexAgents #DataArchitecture

[My CoWork Agent Burned Through $800 in Credits Before Anyone Noticed](https://pub.towardsai.net/my-cowork-agent-burned-through-800-in-credits-before-anyone-noticed-56e15319f6c3) was originally published in [Towards AI](https://pub.towardsai.net) on Medium, where people are continuing the conversation by highlighting and responding to this story.
