Agents are good at working out how to do something, but become expensive and unreliable when they have to work it out again every time. A large part of the work they do every week is an operation they have done before: size these keywords, look up this customer, sync this data with the CRM.
I think Tasks are a good extension for that, and qbash Tasks in particular. A Task is a Python function that qbash hosts and runs, with AI steps that can call different models. Agents reach them through a qbash MCP server, which exposes connectors and Tasks to Claude Code, Codex and Grok Bot, and lets the agent build, list and run Tasks itself.
I suspect Tasks end up as the platform underneath agents, with a growing share of them written by the agents. We'll be publishing more on that.

Sizing Google Ads keywords this week
This week I was working through our Google Ads keywords with Claude Code, sizing searches like "reddit mcp" and "hubspot mcp" for new campaigns. It called our Google Ads keyword tool directly for 70 keywords, and the response came back at 127,403 characters.
That is over Claude Code's limit for a single tool result. Most of the response was twelve months of search history for every keyword. I only wanted the average, but the keyword tool has no option to leave the history out. There was no efficient way to get the tiny piece of information I needed without blowing through a large amount of context along the way.
I use the qbash MCP server with Claude Code, so I asked it to build a Task:
Given a list of keywords, make one batched Google Ads call and return the keyword, average monthly searches, competition, low bid, high bid and average CPC. Leave out the monthly history. No writes or model calls.
It generated a qbash Task, including tests against a mocked SDK. Given three keywords, the Task returns this structured payload in about two seconds:
{
"currency": "CAD",
"rows": [
{"keyword": "notion mcp", "searches": 4400, "competition": "LOW",
"low_bid": 0.1, "high_bid": 17.44, "avg_cpc": 2.86},
{"keyword": "hubspot mcp", "searches": 1300, "competition": "LOW",
"low_bid": 6.57, "high_bid": 82.2, "avg_cpc": 13.19},
{"keyword": "reddit mcp", "searches": 720, "competition": "LOW",
"low_bid": 2.24, "high_bid": 12.7, "avg_cpc": 3.3}
]
}The generated Task looks like this, minus the helpers that parse inputs and convert micros:
# Pick the ad account. With one account this could just be a default input. listing = qbash.integrations.google_ads.list_customers(max_accounts=10) picked = next( (c for c in listing.get("customers", []) if not c.get("manager")), None ) customer_id = str(picked.get("customer_id")) currency = picked.get("currency_code") or None resp = qbash.integrations.google_ads.generate_keyword_historical_metrics( customer_id=customer_id, keywords=keywords, language=language, geo_target_constants=geos, historical_metrics_options={"include_average_cpc": True}, ) rows = [] for kw in keywords: m = by_text[_norm(kw)].get("keyword_metrics") or {} rows.append({ "keyword": kw, "searches": _int(m.get("avg_monthly_searches")), "competition": _comp(m.get("competition")), "low_bid": _money(m.get("low_top_of_page_bid_micros")), "high_bid": _money(m.get("high_top_of_page_bid_micros")), "avg_cpc": _money(m.get("average_cpc_micros")), }) rows.sort(key=lambda x: (x["searches"] is None, -(x["searches"] or 0))) # Often the Task keeps going from here: drop keywords we already bid on, # join to last month's signups. None of that reaches the agent's session. qbash.output({"customer_id": customer_id, "currency": currency, "rows": rows})
Less context, same answer
The Task moves reasoning that an agent would otherwise repeat every time into code. It returns only the pieces of information I need, rather than everything produced along the way.
Across 70 keywords, that meant Claude Code received 7,960 characters instead of 66,037:
- 88% fewer characters reach the agent. 7,960 from the Task against 66,037 from the connector tool.
- About 14,500 fewer tokens per lookup. Roughly 2,000 instead of 16,500.
- One tool call instead of two. The Task looks up the Google Ads account itself.
- 2.3 seconds per run.
This smaller payload, saving context and letting my agent run further, is one reason we really like qbash Tasks. The other is that the operation no longer runs in an agent runtime, which means it is not burning tokens understanding how to solve the problem every time. Account selection, the Google Ads call and response shaping are represented in code, so we can trust the process to run reliably every time. It is easy to create tests, and we only spend tokens on the steps where we really need AI.
This is what I mean by Tasks being an extension for agents. An agent can work something out once, write it down as a Task and call it from then on.