Skip to content

agents-core

The @philschmid/agents-core package provides the foundational primitives for building AI agents with the Gemini Interactions API. It’s designed to be minimal, flexible, and framework-agnostic.

  • agentLoop: One-shot agent execution with streaming event output
  • AgentTool: Flexible tool definition via JSON Schema
  • Event Stream: Real-time updates: text deltas, tool calls, errors, completion

This is the low-level building block. For higher-level features like hooks, built-in tools, sessions, and skills, see the @philschmid/agent package.


Terminal window
bun add @philschmid/agents-core
Terminal window
export GEMINI_API_KEY="your-api-key"

Choose agents-core when you need:

  • Full control over the agent loop and event handling
  • Custom tooling infrastructure
  • Minimal dependencies
  • Building your own framework layer

Choose @philschmid/agent when you need:

  • Built-in tools (read, write, bash, grep)
  • Lifecycle hooks for control flow
  • Multi-turn session management
  • Skills and subagents

The core function for executing agent tasks. It runs a complete agentic loop with tool calling and returns an event stream:

import { agentLoop, printStream } from '@philschmid/agents-core';
const stream = agentLoop(
[{ type: 'text', text: 'Analyze this code and suggest improvements' }],
{ model: 'gemini-3-flash-preview', tools: [analyzerTool] }
);
await printStream(stream, { verbosity: 'verbose' });

For multi-turn conversations, use previousInteractionId to chain interactions:

// Turn 1
const stream1 = agentLoop([{ type: 'text', text: 'Hello' }], { model: 'gemini-3-flash-preview' });
for await (const event of stream1) { /* handle events */ }
const result1 = await stream1.result();
// Turn 2 - chain with previous interaction
const stream2 = agentLoop([{ type: 'text', text: 'What did I say?' }], {
model: 'gemini-3-flash-preview',
previousInteractionId: result1.interactionId,
});

For a higher-level multi-turn API, see AgentSession in the @philschmid/agent package.


Tools use JSON Schema for parameters and an async execute function:

import { type AgentTool } from '@philschmid/agents-core';
import * as fs from 'node:fs';
const listDirTool: AgentTool = {
name: 'list_dir',
label: 'List Directory',
description: 'Lists the contents of a directory.',
parameters: {
type: 'object',
properties: {
directory_path: { type: 'string', description: 'Path to directory' },
},
required: ['directory_path'],
},
execute: async (_id, args) => {
const items = fs.readdirSync(args.directory_path as string);
return { result: items.join(', ') };
},
};

The agent loop emits events as an async generator:

Event TypeDescription
agent.startAgent loop begins
interaction.startLLM call begins
text.startText block begins
text.deltaStreaming text chunk
text.endText block completes
thought.summaryThinking summary from model
tool.startTool execution begins
tool.deltaStreaming tool update
tool.endTool execution completes
interaction.endLLM call completes
agent.endAgent loop finishes
for await (const event of stream) {
switch (event.type) {
case 'text.delta':
process.stdout.write(event.delta);
break;
case 'tool.start':
console.log(`Calling: ${event.name}`);
break;
case 'agent.end':
console.log('Done!');
break;
}
}

  • Agent Loop: Detailed execution flow
  • Tools: Tool interface and patterns
  • Session: Multi-turn conversations with @philschmid/agent
  • Quickstart: Get started in 5 minutes