
Agent Loops
- 15 installs
- 213 repo stars
- Updated August 4, 2026
- yonatangross/orchestkit
Helps with ai & agent building tasks.
About
agent-loops is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted coding.
- agent-loops
- AI & Agent Building
- AI-coding skill
Agent Loops by the numbers
- 15 all-time installs (skills.sh)
- Ranked #11,169 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/yonatangross/orchestkit --skill agent-loopsAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 15 |
|---|---|
| repo stars | ★ 213 |
| Last updated | August 4, 2026 |
| Repository | yonatangross/orchestkit ↗ |
What it does
Helps with ai & agent building tasks.
Files
Agent Loops
Enable LLMs to reason, plan, and take autonomous actions.
ReAct Pattern (Reasoning + Acting)
REACT_PROMPT = """You are an agent that reasons step by step.
For each step, respond with:
Thought: [your reasoning about what to do next]
Action: [tool_name(arg1, arg2)]
Observation: [you'll see the result here]
When you have the final answer:
Thought: I now have enough information
Final Answer: [your response]
Available tools: {tools}
Question: {question}
"""
async def react_loop(question: str, tools: dict, max_steps: int = 10) -> str:
"""Execute ReAct reasoning loop."""
history = REACT_PROMPT.format(tools=list(tools.keys()), question=question)
for step in range(max_steps):
response = await llm.chat([{"role": "user", "content": history}])
history += response.content
# Check for final answer
if "Final Answer:" in response.content:
return response.content.split("Final Answer:")[-1].strip()
# Extract and execute action
if "Action:" in response.content:
action = parse_action(response.content)
result = await tools[action.name](*action.args)
history += f"\nObservation: {result}\n"
return "Max steps reached without answer"Plan-and-Execute Pattern
async def plan_and_execute(goal: str) -> str:
"""Create plan first, then execute steps."""
# 1. Generate plan
plan = await llm.chat([{
"role": "user",
"content": f"Create a step-by-step plan to: {goal}\n\nFormat as numbered list."
}])
steps = parse_plan(plan.content)
results = []
# 2. Execute each step
for i, step in enumerate(steps):
result = await execute_step(step, context=results)
results.append({"step": step, "result": result})
# 3. Check if replanning needed
if should_replan(results):
return await plan_and_execute(
f"{goal}\n\nProgress so far: {results}"
)
# 4. Synthesize final answer
return await synthesize(goal, results)Self-Correction Loop
async def self_correcting_agent(task: str, max_retries: int = 3) -> str:
"""Agent that validates and corrects its own output."""
for attempt in range(max_retries):
# Generate response
response = await llm.chat([{
"role": "user",
"content": task
}])
# Self-validate
validation = await llm.chat([{
"role": "user",
"content": f"""Validate this response for the task: {task}
Response: {response.content}
Check for:
1. Correctness - Is it factually accurate?
2. Completeness - Does it fully answer the task?
3. Format - Is it properly formatted?
If valid, respond: VALID
If invalid, respond: INVALID: [what's wrong and how to fix]"""
}])
if "VALID" in validation.content:
return response.content
# Correct based on feedback
task = f"{task}\n\nPrevious attempt had issues: {validation.content}"
return response.content # Return best attemptMemory Management
class AgentMemory:
"""Sliding window memory for agents."""
def __init__(self, max_messages: int = 20):
self.messages = []
self.max_messages = max_messages
self.summary = ""
def add(self, role: str, content: str):
self.messages.append({"role": role, "content": content})
# Summarize old messages when window full
if len(self.messages) > self.max_messages:
self._compress()
def _compress(self):
"""Summarize oldest messages."""
old = self.messages[:10]
self.messages = self.messages[10:]
# Async summarize would be better
summary = summarize(old)
self.summary = f"{self.summary}\n{summary}"
def get_context(self) -> list:
"""Get messages with summary prefix."""
context = []
if self.summary:
context.append({
"role": "system",
"content": f"Previous context summary: {self.summary}"
})
return context + self.messagesKey Decisions
| Decision | Recommendation |
|---|---|
| Max steps | 5-15 (prevent infinite loops) |
| Temperature | 0.3-0.7 (balance creativity/focus) |
| Memory window | 10-20 messages |
| Validation | Every 3-5 steps |
Common Mistakes
- No step limit (infinite loops)
- No memory management (context overflow)
- No error recovery (crashes on tool failure)
- Over-complex prompts (agent gets confused)
Related Skills
function-calling- Tool definitions and executionmulti-agent-orchestration- Coordinating multiple agentslanggraph-workflows- Stateful agent graphs
Capability Details
react-loop
Keywords: react, reason, act, observe, loop Solves:
- Implement ReAct pattern
- Create reasoning loops
- Build iterative agents
tool-use
Keywords: tool, function, call, execution Solves:
- Implement tool calling
- Execute functions from LLM
- Parse tool responses
workflow-template
Keywords: template, workflow, agent, typescript Solves:
- Agent workflow template
- TypeScript implementation
- Copy-paste starter
/**
* Agentic Workflow Template
* Implements autonomous agents with tool use and ReAct pattern
*/
import OpenAI from 'openai'
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY })
// =============================================
// 1. TOOL DEFINITIONS
// =============================================
interface Tool {
name: string
description: string
parameters: {
type: 'object'
properties: Record<string, any>
required: string[]
}
execute: (args: any) => Promise<any>
}
const tools: Tool[] = [
{
name: 'search_web',
description: 'Search the web for current information',
parameters: {
type: 'object',
properties: {
query: { type: 'string', description: 'Search query' }
},
required: ['query']
},
execute: async ({ query }) => {
// Implement web search
return { results: [`Search results for: ${query}`] }
}
},
{
name: 'query_database',
description: 'Query the internal database',
parameters: {
type: 'object',
properties: {
query: { type: 'string', description: 'SQL query or natural language' }
},
required: ['query']
},
execute: async ({ query: _query }) => {
// Implement database query
return { rows: [] }
}
},
{
name: 'send_email',
description: 'Send an email to a user',
parameters: {
type: 'object',
properties: {
to: { type: 'string', description: 'Email address' },
subject: { type: 'string', description: 'Email subject' },
body: { type: 'string', description: 'Email body' }
},
required: ['to', 'subject', 'body']
},
execute: async ({ to: _to, subject: _subject, body: _body }) => {
// Implement email sending
return { sent: true, messageId: 'msg_123' }
}
}
]
// =============================================
// 2. REACT AGENT (Reasoning + Acting)
// =============================================
interface AgentStep {
thought: string
action?: string
actionInput?: unknown
observation?: string
}
interface AgentResult {
answer: string
steps: AgentStep[]
totalCost: number
iterations: number
}
/**
* Parse agent response into step components
*/
function parseAgentResponse(content: string): { thought: string; action?: string; actionInput?: string } {
const thoughtMatch = content.match(/Thought: (.*?)(?=\nAction:|$)/s)
const actionMatch = content.match(/Action: (.*?)(?=\n|$)/)
const inputMatch = content.match(/Action Input: (.*?)(?=\n|$)/)
return {
thought: thoughtMatch?.[1]?.trim() || '',
action: actionMatch?.[1]?.trim(),
actionInput: inputMatch?.[1]?.trim()
}
}
/**
* Execute a tool and return the observation
*/
async function executeTool(action: string, actionInput: unknown): Promise<string> {
const tool = tools.find(t => t.name === action)
if (!tool) {
return `Error: Tool '${action}' not found`
}
const result = await tool.execute(actionInput as Record<string, unknown>)
return JSON.stringify(result, null, 2)
}
export async function reactAgent(
task: string,
options: {
maxIterations?: number
verbose?: boolean
} = {}
): Promise<AgentResult> {
const { maxIterations = 10, verbose = false } = options
const steps: AgentStep[] = []
let totalCost = 0
const systemPrompt = `You are an autonomous agent that can use tools to complete tasks.
Available tools:
${tools.map(t => `- ${t.name}: ${t.description}`).join('\n')}
Use this exact format for each step:
Thought: [Your reasoning about what to do next]
Action: [tool name]
Action Input: {"param": "value"}
Observation: [Tool result will appear here]
Repeat Thought/Action/Observation until you have enough information.
Then provide:
Answer: [Final answer to the user's task]
IMPORTANT:
- Use tools when you need information
- Think step by step
- Only use available tools
- Action Input must be valid JSON
`
const messages = [
{ role: 'system' as const, content: systemPrompt },
{ role: 'user' as const, content: task }
]
for (let i = 0; i < maxIterations; i++) {
const response = await openai.chat.completions.create({
model: 'gpt-5.2',
messages,
temperature: 0.1
})
const content = response.choices[0].message.content!
totalCost += (response.usage!.total_tokens / 1000) * 0.01
if (verbose) {
console.log(`\n--- Iteration ${i + 1} ---`)
console.log(content)
}
// Check for final answer
if (content.includes('Answer:')) {
const answer = content.split('Answer:')[1].trim()
return { answer, steps, totalCost, iterations: i + 1 }
}
// Parse thought, action, and input
const parsed = parseAgentResponse(content)
const step: AgentStep = { thought: parsed.thought }
if (parsed.action && parsed.actionInput) {
step.action = parsed.action
try {
step.actionInput = JSON.parse(parsed.actionInput)
step.observation = await executeTool(parsed.action, step.actionInput)
} catch (err) {
step.observation = `Error: ${err instanceof Error ? err.message : 'Unknown error'}`
}
}
steps.push(step)
// Add step to messages
messages.push({
role: 'assistant',
content
})
if (step.observation) {
messages.push({
role: 'user',
content: `Observation: ${step.observation}`
})
}
}
throw new Error(`Agent exceeded max iterations (${maxIterations})`)
}
// =============================================
// 3. FUNCTION CALLING AGENT
// =============================================
export async function functionCallingAgent(task: string): Promise<AgentResult> {
const steps: AgentStep[] = []
let totalCost = 0
const messages = [
{ role: 'system' as const, content: 'You are a helpful assistant with access to tools.' },
{ role: 'user' as const, content: task }
]
const openaiTools = tools.map(tool => ({
type: 'function' as const,
function: {
name: tool.name,
description: tool.description,
parameters: tool.parameters
}
}))
let iteration = 0
while (iteration < 10) {
const response = await openai.chat.completions.create({
model: 'gpt-5.2',
messages,
tools: openaiTools
})
const message = response.choices[0].message
totalCost += (response.usage!.total_tokens / 1000) * 0.01
// No tool calls - final answer
if (!message.tool_calls) {
return {
answer: message.content!,
steps,
totalCost,
iterations: iteration + 1
}
}
// Execute tool calls
messages.push(message as any)
for (const toolCall of message.tool_calls) {
const tool = tools.find(t => t.name === toolCall.function.name)
if (!tool) continue
const args = JSON.parse(toolCall.function.arguments)
const result = await tool.execute(args)
steps.push({
thought: `Calling ${toolCall.function.name}`,
action: toolCall.function.name,
actionInput: args,
observation: JSON.stringify(result)
})
messages.push({
role: 'tool',
tool_call_id: toolCall.id,
content: JSON.stringify(result)
})
}
iteration++
}
throw new Error('Agent exceeded max iterations')
}
// =============================================
// 4. MULTI-AGENT SYSTEM
// =============================================
interface Agent {
name: string
role: string
tools: Tool[]
systemPrompt: string
}
export async function multiAgentCollaboration(
task: string,
agents: Agent[]
): Promise<AgentResult> {
const steps: AgentStep[] = []
let totalCost = 0
// 1. Coordinator plans the task
const planResponse = await openai.chat.completions.create({
model: 'gpt-5.2',
messages: [
{
role: 'system',
content: `You are a coordinator. Break down tasks and assign to agents:
${agents.map(a => `- ${a.name}: ${a.role}`).join('\n')}
Provide a numbered plan with agent assignments.`
},
{
role: 'user',
content: `Task: ${task}\n\nProvide a step-by-step plan.`
}
]
})
const plan = planResponse.choices[0].message.content!
totalCost += (planResponse.usage!.total_tokens / 1000) * 0.01
steps.push({
thought: 'Coordinator planning',
observation: plan
})
// 2. Execute agent subtasks (simplified - in production, parse plan and execute)
const agentResults = await Promise.all(
agents.map(async (agent) => {
const response = await openai.chat.completions.create({
model: 'gpt-5.2',
messages: [
{ role: 'system', content: agent.systemPrompt },
{ role: 'user', content: `Task: ${task}\n\nPlan:\n${plan}\n\nComplete your part.` }
]
})
totalCost += (response.usage!.total_tokens / 1000) * 0.01
return {
agent: agent.name,
result: response.choices[0].message.content!
}
})
)
// 3. Synthesize results
const synthesisResponse = await openai.chat.completions.create({
model: 'gpt-5.2',
messages: [
{
role: 'system',
content: 'Synthesize agent results into a coherent final answer.'
},
{
role: 'user',
content: `Task: ${task}\n\nAgent Results:\n${JSON.stringify(agentResults, null, 2)}`
}
]
})
totalCost += (synthesisResponse.usage!.total_tokens / 1000) * 0.01
return {
answer: synthesisResponse.choices[0].message.content!,
steps,
totalCost,
iterations: agents.length + 2 // plan + agents + synthesis
}
}
// =============================================
// 5. USAGE EXAMPLES
// =============================================
export async function exampleReActAgent() {
const result = await reactAgent(
'Find the latest news about AI and send a summary to user@example.com',
{ verbose: true }
)
console.log('\n=== Final Answer ===')
console.log(result.answer)
console.log(`\nCost: $${result.totalCost.toFixed(4)}`)
console.log(`Iterations: ${result.iterations}`)
}
export async function exampleFunctionCalling() {
const result = await functionCallingAgent(
'Search for React Server Components tutorials and save the top 3 to the database'
)
console.log(result.answer)
}
export async function exampleMultiAgent() {
const agents: Agent[] = [
{
name: 'Researcher',
role: 'Research and gather information',
tools: [tools[0]], // web search
systemPrompt: 'You are a researcher. Find accurate, up-to-date information.'
},
{
name: 'Analyst',
role: 'Analyze data and extract insights',
tools: [tools[1]], // database
systemPrompt: 'You are an analyst. Find patterns and insights in data.'
},
{
name: 'Communicator',
role: 'Draft communications',
tools: [tools[2]], // email
systemPrompt: 'You are a communicator. Write clear, professional messages.'
}
]
const result = await multiAgentCollaboration(
'Research AI trends, analyze our internal data, and send a weekly report',
agents
)
console.log(result.answer)
}
Related skills
AI & Agent Buildingagents