{"id":"7a69c019-8825-40c6-9191-b1d4afe618d3","shortId":"yk4n5k","kind":"skill","title":"query-loop-implementation","tagline":"Implement a production-ready LLM query loop / agent loop for AI applications. Use this skill whenever the user wants to add tool calling, ReAct-style reasoning-action-observation cycles, function calling loops, query engines, agent runtimes, tool_result feedback, max-turn exits, ","description":"# Query Loop Implementation\n\n## Core Idea\n\nBuild the loop as product infrastructure, not prompt glue:\n\n```text\nConversationManager -> QueryLoop -> ToolRuntime\n```\n\n- `ConversationManager` owns durable state: session id, messages, user settings, budget, persistence.\n- `QueryLoop` owns one task turn: call model, detect tool calls, execute tools, append tool results, repeat.\n- `ToolRuntime` owns registered tools: schemas, permission checks, execution, error formatting.\n\nUse ReAct as the mental model:\n\n```text\nThought -> Action -> Observation -> Thought -> Answer\n```\n\nImplement it as structured API traffic:\n\n```text\nmodel thinking/text -> tool_call -> tool_result -> next model call -> final text\n```\n\n## Implementation Workflow\n\n1. Inspect the user's stack and current LLM call site.\n   Find where messages are built, where the model is called, and whether tool/function calling is already configured.\n\n2. Introduce a minimal query loop.\n   Keep the first version narrow: one model call function, one tool registry, explicit exit conditions.\n\n3. Normalize message shapes.\n   Use the provider's structured tool-call format when available. Avoid parsing free-form `Action:` text unless the provider has no function/tool-calling API.\n\n4. Add tool execution safety.\n   Validate tool input against a schema, apply permission checks for risky tools, wrap failures as tool results, and log every call.\n\n5. Add exit and budget guards before expanding features.\n   Always include `maxTurns`, timeout/cancel support, token/cost budget checks, and a fatal-error path.\n\n6. Keep context-window strategy outside this skill.\n   Accept `messages` as loop input and return updated `messages`, but leave trimming, retrieval, summarization, and compaction to a separate context-management layer.\n\n## Minimal Loop\n\nAdapt this shape to the user's language and SDK:\n\n```ts\nasync function runQueryLoop({\n  initialMessages,\n  model,\n  tools,\n  maxTurns = 10,\n  signal,\n}: {\n  initialMessages: Message[]\n  model: ModelClient\n  tools: ToolRegistry\n  maxTurns?: number\n  signal?: AbortSignal\n}) {\n  let messages = [...initialMessages]\n\n  for (let turn = 1; turn <= maxTurns; turn++) {\n    if (signal?.aborted) return { status: \"aborted\", messages }\n\n    const response = await model.generate({\n      messages,\n      tools: tools.definitions(),\n      signal,\n    })\n\n    messages.push(response.message)\n\n    const toolCalls = extractToolCalls(response.message)\n    if (toolCalls.length === 0) {\n      return {\n        status: \"completed\",\n        finalMessage: response.message,\n        messages,\n      }\n    }\n\n    for (const call of toolCalls) {\n      const result = await tools.execute(call, { signal, messages })\n      messages.push(makeToolResultMessage(call.id, result))\n    }\n  }\n\n  return { status: \"max_turns\", messages }\n}\n```\n\nThe \"model continues judging\" step is not a separate function. It happens when the loop calls the model again after appending `tool_result` messages.\n\n## Required Exit Conditions\n\nImplement these before shipping:\n\n- **Normal completion**: the model response has no tool calls.\n- **Max turns**: stop after a fixed number of model-tool cycles.\n- **Abort/timeout**: stop when the user cancels or the request exceeds its deadline.\n- **Permission denied**: stop or return a tool error depending on the product's safety policy.\n- **Budget exceeded**: stop when token, cost, or runtime budget is exhausted.\n- **Fatal tool error**: stop when a tool failure cannot be corrected by the model.\n\nPrefer returning structured terminal reasons:\n\n```ts\ntype TerminalReason =\n  | \"completed\"\n  | \"max_turns\"\n  | \"aborted\"\n  | \"timeout\"\n  | \"permission_denied\"\n  | \"budget_exceeded\"\n  | \"fatal_tool_error\"\n```\n\n## Tool Runtime Contract\n\nEach tool should define:\n\n```ts\ntype Tool = {\n  name: string\n  description: string\n  inputSchema: unknown\n  risk: \"read\" | \"write\" | \"execute\" | \"external\"\n  validate(input: unknown): ValidatedInput\n  canUse(input: ValidatedInput, ctx: ToolContext): Promise<PermissionDecision>\n  call(input: ValidatedInput, ctx: ToolContext): Promise<ToolResult>\n}\n```\n\nExecution order:\n\n```text\nfind tool by name\n-> schema validate model input\n-> run tool-specific validation\n-> check permission\n-> call tool\n-> format success or error as tool_result\n```\n\nReturn tool errors to the model when it can plausibly recover, for example invalid arguments, file not found, empty search result, or transient API errors. Stop the loop for security violations, repeated failures, missing credentials, or budget exhaustion.\n\n## Product Design Guidance\n\nKeep \"intelligence\" in the model and \"reliability\" in code:\n\n- Let the model decide whether it needs another tool call.\n- Let code enforce schemas, permissions, budgets, and loop exits.\n- Keep prompts focused on tool semantics and task policy.\n- Keep implementation focused on deterministic control flow.\n\nFor simple AI apps, avoid subagents, worktrees, and streaming tool execution at first. Add them only when the product actually needs parallel work, isolation, or long-running tasks.\n\n## When More Detail Is Needed\n\nRead `references/query-loop-patterns.md` when designing a new query engine, reviewing an existing implementation, or explaining ReAct-to-query-loop architecture to another engineer.","tags":["query","loop","implementation","book2skills","simbajigege","agent-skills","agentskills","anthropic","anthropic-claude","growth-investing","investing","investing-skills"],"capabilities":["skill","source-simbajigege","skill-query-loop-implementation","topic-agent-skills","topic-agentskills","topic-anthropic","topic-anthropic-claude","topic-book2skills","topic-growth-investing","topic-investing","topic-investing-skills","topic-skills","topic-stock-analysis"],"categories":["book2skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/simbajigege/book2skills/query-loop-implementation","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add simbajigege/book2skills","source_repo":"https://github.com/simbajigege/book2skills","install_from":"skills.sh"}},"qualityScore":"0.479","qualityRationale":"deterministic score 0.48 from registry signals: · indexed on github topic:agent-skills · 58 github stars · SKILL.md body (5,262 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-05-18T18:57:21.327Z","embedding":null,"createdAt":"2026-05-18T06:56:51.278Z","updatedAt":"2026-05-18T18:57:21.327Z","lastSeenAt":"2026-05-18T18:57:21.327Z","tsv":"'0':362 '1':138,335 '10':317 '2':166 '3':187 '4':216 '5':242 '6':265 'abort':341,344,505 'abort/timeout':442 'abortsign':328 'accept':274 'action':34,114,207 'actual':682 'adapt':299 'add':26,217,243,676 'agent':13,42 'ai':16,665 'alreadi':164 'alway':251 'anoth':635,718 'answer':117 'api':122,215,601 'app':666 'append':92,410 'appli':227 'applic':17 'architectur':716 'argument':592 'async':310 'avail':201 'avoid':202,667 'await':348,376 'budget':78,246,257,469,477,509,614,643 'build':56 'built':153 'call':28,38,85,89,128,133,147,158,162,179,198,241,371,378,405,429,545,569,637 'call.id':383 'cancel':447 'cannot':488 'canus':539 'check':102,229,258,567 'code':627,639 'compact':289 'complet':365,422,502 'condit':186,416 'configur':165 'const':346,356,370,374 'context':268,294 'context-manag':293 'context-window':267 'continu':392 'contract':516 'control':661 'conversationmanag':66,69 'core':54 'correct':490 'cost':474 'credenti':612 'ctx':542,548 'current':145 'cycl':36,441 'deadlin':453 'decid':631 'defin':520 'deni':455,508 'depend':462 'descript':526 'design':617,700 'detail':694 'detect':87 'determinist':660 'durabl':71 'empti':596 'enforc':640 'engin':41,704,719 'error':104,263,461,482,513,574,580,602 'everi':240 'exampl':590 'exceed':451,470,510 'execut':90,103,219,533,551,673 'exhaust':479,615 'exist':707 'exit':50,185,244,415,646 'expand':249 'explain':710 'explicit':184 'extern':534 'extracttoolcal':358 'failur':234,487,610 'fatal':262,480,511 'fatal-error':261 'featur':250 'feedback':46 'file':593 'final':134 'finalmessag':366 'find':149,554 'first':174,675 'fix':435 'flow':662 'focus':649,658 'form':206 'format':105,199,571 'found':595 'free':205 'free-form':204 'function':37,180,311,399 'function/tool-calling':214 'glue':64 'guard':247 'guidanc':618 'happen':401 'id':74 'idea':55 'implement':4,5,53,118,136,417,657,708 'includ':252 'infrastructur':61 'initialmessag':313,319,331 'input':223,278,536,540,546,561 'inputschema':528 'inspect':139 'intellig':620 'introduc':167 'invalid':591 'isol':686 'judg':393 'keep':172,266,619,647,656 'languag':306 'layer':296 'leav':284 'let':329,333,628,638 'llm':10,146 'log':239 'long':689 'long-run':688 'loop':3,12,14,39,52,58,171,277,298,404,605,645,715 'maketoolresultmessag':382 'manag':295 'max':48,387,430,503 'max-turn':47 'maxturn':253,316,325,337 'mental':110 'messag':75,151,189,275,282,320,330,345,350,368,380,389,413 'messages.push':354,381 'minim':169,297 'miss':611 'model':86,111,125,132,156,178,314,321,391,407,424,439,493,560,583,623,630 'model-tool':438 'model.generate':349 'modelcli':322 'name':524,557 'narrow':176 'need':634,683,696 'new':702 'next':131 'normal':188,421 'number':326,436 'observ':35,115 'one':82,177,181 'order':552 'outsid':271 'own':70,81,97 'parallel':684 'pars':203 'path':264 'permiss':101,228,454,507,568,642 'persist':79 'plausibl':587 'polici':468,655 'prefer':494 'product':8,60,465,616,681 'production-readi':7 'promis':544,550 'prompt':63,648 'provid':193,211 'queri':2,11,40,51,170,703,714 'query-loop-implement':1 'queryloop':67,80 'react':30,107,712 'react-styl':29 'react-to-query-loop':711 'read':531,697 'readi':9 'reason':33,498 'reasoning-action-observ':32 'recov':588 'references/query-loop-patterns.md':698 'regist':98 'registri':183 'reliabl':625 'repeat':95,609 'request':450 'requir':414 'respons':347,425 'response.message':355,359,367 'result':45,94,130,237,375,384,412,577,598 'retriev':286 'return':280,342,363,385,458,495,578 'review':705 'risk':530 'riski':231 'run':562,690 'runqueryloop':312 'runtim':43,476,515 'safeti':220,467 'schema':100,226,558,641 'sdk':308 'search':597 'secur':607 'semant':652 'separ':292,398 'session':73 'set':77 'shape':190,301 'ship':420 'signal':318,327,340,353,379 'simpl':664 'site':148 'skill':20,273 'skill-query-loop-implementation' 'source-simbajigege' 'specif':565 'stack':143 'state':72 'status':343,364,386 'step':394 'stop':432,443,456,471,483,603 'strategi':270 'stream':671 'string':525,527 'structur':121,195,496 'style':31 'subag':668 'success':572 'summar':287 'support':255 'task':83,654,691 'termin':497 'terminalreason':501 'text':65,112,124,135,208,553 'thinking/text':126 'thought':113,116 'timeout':506 'timeout/cancel':254 'token':473 'token/cost':256 'tool':27,44,88,91,93,99,127,129,182,197,218,222,232,236,315,323,351,411,428,440,460,481,486,512,514,518,523,555,564,570,576,579,636,651,672 'tool-cal':196 'tool-specif':563 'tool/function':161 'toolcal':357,373 'toolcalls.length':361 'toolcontext':543,549 'toolregistri':324 'toolruntim':68,96 'tools.definitions':352 'tools.execute':377 'topic-agent-skills' 'topic-agentskills' 'topic-anthropic' 'topic-anthropic-claude' 'topic-book2skills' 'topic-growth-investing' 'topic-investing' 'topic-investing-skills' 'topic-skills' 'topic-stock-analysis' 'traffic':123 'transient':600 'trim':285 'ts':309,499,521 'turn':49,84,334,336,338,388,431,504 'type':500,522 'unknown':529,537 'unless':209 'updat':281 'use':18,106,191 'user':23,76,141,304,446 'valid':221,535,559,566 'validatedinput':538,541,547 'version':175 'violat':608 'want':24 'whenev':21 'whether':160,632 'window':269 'work':685 'workflow':137 'worktre':669 'wrap':233 'write':532","prices":[{"id":"eca4685b-1815-4fba-8df9-394712803c6d","listingId":"7a69c019-8825-40c6-9191-b1d4afe618d3","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"simbajigege","category":"book2skills","install_from":"skills.sh"},"createdAt":"2026-05-18T06:56:51.278Z"}],"sources":[{"listingId":"7a69c019-8825-40c6-9191-b1d4afe618d3","source":"github","sourceId":"simbajigege/book2skills/query-loop-implementation","sourceUrl":"https://github.com/simbajigege/book2skills/tree/main/skills/query-loop-implementation","isPrimary":false,"firstSeenAt":"2026-05-18T06:56:51.278Z","lastSeenAt":"2026-05-18T18:57:21.327Z"}],"details":{"listingId":"7a69c019-8825-40c6-9191-b1d4afe618d3","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"simbajigege","slug":"query-loop-implementation","github":{"repo":"simbajigege/book2skills","stars":58,"topics":["agent-skills","agentskills","anthropic","anthropic-claude","book2skills","growth-investing","investing","investing-skills","skills","stock-analysis"],"license":"mit","html_url":"https://github.com/simbajigege/book2skills","pushed_at":"2026-05-18T05:19:31Z","description":"Create best skills based on best books","skill_md_sha":"36084b5970bd0053878be1a40224cb6dc4943f5c","skill_md_path":"skills/query-loop-implementation/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/simbajigege/book2skills/tree/main/skills/query-loop-implementation"},"layout":"multi","source":"github","category":"book2skills","frontmatter":{"name":"query-loop-implementation","description":"Implement a production-ready LLM query loop / agent loop for AI applications. Use this skill whenever the user wants to add tool calling, ReAct-style reasoning-action-observation cycles, function calling loops, query engines, agent runtimes, tool_result feedback, max-turn exits, or Claude Code-like Agent Loop behavior to their own product or codebase."},"skills_sh_url":"https://skills.sh/simbajigege/book2skills/query-loop-implementation"},"updatedAt":"2026-05-18T18:57:21.327Z"}}