tinyhumansai/openhuman · error · anyhow::Error

Managed cloud tools are disabled because your OpenHuman AI c

Error message

Managed cloud tools are disabled because your OpenHuman AI credits are exhausted. Add credits or route the task to user-supplied providers.

What it means

Thrown by IntegrationClient::ensure_budget_available before any managed call whose path starts with /agent-integrations/ (everything except /agent-integrations/pricing). It probes the hosted team usage endpoint via managed_tool_budget_exhausted (result cached for a TTL); when the OpenHuman AI credit pool that funds managed cloud tools is drained, the client fails fast instead of making the backend round-trip. A failed probe is NOT cached and lets the call through, so seeing this error means the probe succeeded and reported exhausted.

Source

Thrown at src/openhuman/integrations/client.rs:386

            .expect("failed to build integration download HTTP client");

        Self {
            backend_url,
            auth_token,
            budget_config,
            sdk,
            download_client,
            pricing: tokio::sync::OnceCell::new(),
        }
    }

    async fn ensure_budget_available(&self, path: &str) -> anyhow::Result<()> {
        if !managed_budget_applies_to_path(path) {
            return Ok(());
        }
        if let Some(config) = &self.budget_config {
            if crate::openhuman::hosted::team::managed_tool_budget_exhausted(config).await {
                anyhow::bail!(
                    "Managed cloud tools are disabled because your OpenHuman AI credits are exhausted. Add credits or route the task to user-supplied providers."
                );
            }
        }
        Ok(())
    }

    /// POST JSON to a backend endpoint and parse the response `data` field.
    pub async fn post<T: serde::de::DeserializeOwned>(
        &self,
        path: &str,
        body: &serde_json::Value,
    ) -> anyhow::Result<T> {
        self.request_json(reqwest::Method::POST, path, Some(body))
            .await
    }

    /// GET from a backend endpoint and parse the response `data` field.

View on GitHub (pinned to 7491200858)

Solutions

  1. Add OpenHuman AI credits (or raise the team budget cap) in the hosted account/billing UI, then retry after the budget probe cache TTL expires
  2. Route the task to user-supplied provider keys (BYOK) so the call bypasses the managed budget path entirely
  3. Confirm exhaustion first via the team usage RPC (hosted::team::get_usage) to distinguish real exhaustion from other failures

Example fix

// before — every managed call fails while credits are out
client.post("/agent-integrations/composio/execute", &body).await?;

// after — probe the budget gate first, fall back to a user-supplied provider
if let Some(cfg) = &budget_config {
    if openhuman::hosted::team::managed_tool_budget_exhausted(cfg).await {
        return run_with_user_supplied_provider(&body).await;
    }
}
client.post("/agent-integrations/composio/execute", &body).await?;
Defensive patterns

Strategy: fallback

Validate before calling

// Probe the budget gate before a managed call (same TTL-cached check the client uses)
use openhuman::hosted::team::managed_tool_budget_exhausted;

async fn managed_call_allowed(budget_config: &Option<Config>) -> bool {
    match budget_config {
        Some(cfg) => !managed_tool_budget_exhausted(cfg).await,
        None => true, // no budget configured -> gate does not apply
    }
}

Try / catch

match client.post("/agent-integrations/composio/execute", &body).await {
    Ok(resp) => Ok(resp),
    Err(err) if err.to_string().contains("credits are exhausted") => {
        // Budget state, not a bug: switch provider instead of retrying
        run_with_user_supplied_provider(&body).await
    }
    Err(err) => Err(err),
}

Prevention

When it happens

Trigger: Any IntegrationClient.post/get/raw_delete to a /agent-integrations/* path (e.g. POST /agent-integrations/composio/execute, the Composio trigger endpoints) while team.get_usage reports the managed tool budget exhausted. Because the exhausted flag is TTL-cached, the error keeps firing for a short window even immediately after a top-up.

Common situations: Free/trial credits used up mid-task; a team budget cap reached while an agent loop hammers managed Composio tools; a stale cached exhausted flag from just before credits were refilled; shared team account drained by another member.

Related errors


AI-assisted analysis of tinyhumansai/openhuman@7491200858 (2026-08-17). Data as JSON: /api/errors/68e02cd79de819c1. Report an issue: GitHub.