Build a Research Agent

Compose A3S Code v3.1.0 programmatic tool calling, task delegation, streaming, and queue inspection with the Node SDK.

Build a Research Agent

This tutorial combines deterministic local scanning, delegated follow-ups, streaming synthesis, queue inspection, and run replay.

Live web search, remote workers, and third-party MCP servers depend on your runtime environment. Test those integrations in your application before relying on them in production.

Shape

question
-> deterministic local scan with PTC
-> optional delegated child investigations
-> streamed synthesis
-> run and queue inspection

Create a Session

import { Agent } from '@a3s-lab/code';
const agent = await Agent.create('agent.acl');
const session = agent.session(process.cwd(), {
builtinSkills: true,
planningMode: 'enabled',
maxToolRounds: 24,
autoCompact: true,
autoDelegation: { enabled: true, maxTasks: 2 },
autoParallel: false,
});

Deterministic Scan with PTC

Programmatic Tool Calling is the right place for bounded, repeatable tool chains. The runtime exposes ctx.readFile, ctx.read, ctx.grep, ctx.glob, ctx.ls, ctx.bash, ctx.git, and generic ctx.tool.

const scan = await session.program({
source: `
export default async function run(ctx, inputs) {
const files = await ctx.glob(inputs.glob);
const hits = await ctx.grep(inputs.query, { glob: inputs.glob });
const status = await ctx.git('status');
return { files, hits, status };
}
`,
inputs: {
glob: '**/*.{ts,tsx,js,md}',
query: 'authentication',
},
allowedTools: ['glob', 'grep', 'git'],
limits: {
timeoutMs: 30000,
maxToolCalls: 12,
maxOutputBytes: 65536,
},
});
const metadata = JSON.parse(scan.metadataJson);
console.log(metadata.script_result);
console.log(metadata.program.tool_calls);

Delegate Focused Follow-Ups

const investigations = await session.tasks([
{
agent: 'general',
description: 'Auth release blockers',
prompt: 'Inspect authentication error handling and list release blockers.',
maxSteps: 4,
},
{
agent: 'general',
description: 'Auth test coverage',
prompt: 'Inspect tests around authentication edge cases and list missing coverage.',
maxSteps: 4,
},
]);

tasks() returns a ToolResult from the core parallel_task tool.

Stream Synthesis

Consume EventStream with .next():

const stream = await session.stream(`
Write a concise research report.
PTC scan:
${scan.output}
Child investigations:
${investigations.output}
`);
while (true) {
const { value: event, done } = await stream.next();
if (done) break;
if (event?.text) process.stdout.write(event.text);
}

Inspect Queue and Replay State

Queue APIs are session inspection and external-task primitives:

const queued = agent.session(process.cwd(), {
queueConfig: { enableDlq: true, enableMetrics: true },
});
console.log(queued.hasQueue());
console.log(await queued.queueStats());
console.log(await queued.queueMetrics());
console.log(await queued.pendingExternalTasks());
console.log(await queued.deadLetters());
for (const run of await session.runs()) {
console.log(run.id, run.status, await session.runEvents(run.id));
}

Use this as a local research workflow. Add live web, remote workers, or third-party MCP servers after testing those services in your deployment environment.