@morphixai/agent-framework
v0.2.8
Published
Declarative multi-agent framework on top of @morphixai/agent-core — define agents/tools/skills, plug an LLM, run routing/streaming.
Maintainers
Readme
@morphixai/agent-framework
Declarative multi-agent framework on top of
@morphixai/agent-core
(Context Flow Protocol).
You define agents / tools / skills and plug in an LLM + resources; the framework handles routing, the fork-tree, the tool-calling loop (LangGraph), persistence, SSE streaming, and lifecycle hooks.
Install
npm install @morphixai/agent-frameworkPeer ecosystem: @langchain/core, @langchain/langgraph, zod, and the
companion @morphixai/agent-core / agent-bus / agent-workspace packages
(installed automatically as dependencies).
Quick start
import { createAgentFramework, defineAgent } from '@morphixai/agent-framework';
import { defineTool } from '@morphixai/agent-core';
import { ChatOpenAI } from '@langchain/openai';
import { z } from 'zod';
const writeFile = defineTool({
name: 'write_file',
scope: 'app',
requires: ['userId', 'appId'],
inputSchema: z.object({ path: z.string(), content: z.string() }),
handler: async (ctx, { path, content }) => ctx.scope.resources.fs.write(path, content),
});
const general = defineAgent({
id: 'general',
prompt: 'You are the user-facing agent. Delegate implementation work.',
model: 'gpt-5.4-mini',
tools: ['spawn_agent'],
canSpawn: ['developer'], // ← who this agent may fork
scope: 'user',
});
const developer = defineAgent({
id: 'developer',
prompt: 'You implement features by writing files.',
model: 'gpt-5.4-mini',
tools: ['write_file'],
scope: 'app',
});
const framework = createAgentFramework({
agents: [general, developer],
tools: [writeFile],
chatModel: new ChatOpenAI({ model: 'gpt-5.4-mini' }),
scopeResolver: (identity) => /* map identity -> your Scope union + resources */,
});
const handle = framework.run({ message: 'build me a todo app', threadId: 't-1', userId: 'u-1', scope: 'general' });
for await (const event of handle.events) console.log(event.type, event);
const { ok, finalMessage } = await handle.finished;Multi-agent: fork a tree, run children in parallel
Agents don't call each other directly — the orchestrator agent forks children
with the built-in spawn_agent tool and awaits them with wait_children. Each
child is its own runtime with its own scope, bus node, and workspace; results
flow back up the tree.
const orchestrator = defineAgent({
id: 'orchestrator',
prompt: 'Break the request into parallel sub-tasks, fan them out, then merge results.',
model: 'gpt-5.4-mini',
tools: ['spawn_agent', 'wait_children'],
canSpawn: ['researcher', 'writer'], // allowed child agent ids
scope: 'user',
});
const researcher = defineAgent({ id: 'researcher', prompt: 'Gather facts.', model: 'gpt-5.4-mini', tools: ['web_search'], scope: 'user' });
const writer = defineAgent({ id: 'writer', prompt: 'Draft prose from notes.', model: 'gpt-5.4-mini', tools: [], scope: 'user' });
// What the orchestrator LLM emits at runtime (tool calls, handled by the framework):
//
// const a = await spawn_agent({ agentId: 'researcher', mode: 'async', initialMessage: 'find 2025 EV market stats' });
// const b = await spawn_agent({ agentId: 'writer', mode: 'async', initialMessage: 'outline an intro section' });
// const results = await wait_children({
// runIds: [JSON.parse(a).childRunId, JSON.parse(b).childRunId],
// mode: 'all', // 'all' | 'any' | 'race'
// });
// // results: [{ runId, agentId, taskId, ok, finalMessage?, error? }, ...]
const framework = createAgentFramework({
agents: [orchestrator, researcher, writer],
tools: [/* web_search, ... */],
chatModel: new ChatOpenAI({ model: 'gpt-5.4-mini' }),
scopeResolver,
});Parent ↔ child asks
A child can ask its parent mid-run (ask_parent); answer deterministically with
onAsk (no LLM round-trip) or let the parent's LLM reply via answer_child:
const developer = defineAgent({
id: 'developer',
prompt: 'Implement features. Ask the parent when you need approval.',
model: 'gpt-5.4-mini',
tools: ['write_file', 'ask_parent'],
scope: 'app',
});
const general = defineAgent({
id: 'general',
prompt: 'Supervise the developer.',
model: 'gpt-5.4-mini',
tools: ['spawn_agent', 'answer_child'],
canSpawn: ['developer'],
scope: 'user',
// deterministic policy answer — skips the slow LLM path:
onAsk: async (msg) => ({ approved: msg.payload?.risk !== 'high' }),
});Skills: lazy-loaded domain knowledge
A skill is a knowledge pack an agent loads on demand — three-tier so prompts
stay small: (1) the framework scans agent.skills, (2) injects each skill's
short description into the system prompt, (3) the agent pulls full content at
runtime via the built-in load_skill tool, cached in thread state for the rest
of the conversation. The load backend is yours — local FS, DB, Langfuse,
Notion, S3, anything.
import { defineSkill, defineAgent, createAgentFramework } from '@morphixai/agent-framework';
import { readFile } from 'node:fs/promises';
const refundPolicy = defineSkill({
id: 'refund-policy',
description: 'Company refund rules: eligibility windows, exceptions, escalation paths.',
load: async () => readFile('./knowledge/refund-policy.md', 'utf8'), // any backend
});
const billingSkill = defineSkill({
id: 'billing-api',
description: 'How to call the billing API: endpoints, auth, idempotency keys.',
load: async () => fetchFromLangfuse('billing-api-guide'),
});
const support = defineAgent({
id: 'support',
prompt: 'You are a support agent. Consult your skills before answering policy questions.',
model: 'gpt-5.4-mini',
tools: ['load_skill'], // built-in tool that fetches full skill content
skills: ['refund-policy', 'billing-api'], // descriptions auto-injected into the prompt
scope: 'user',
});
const framework = createAgentFramework({
agents: [support],
skills: [refundPolicy, billingSkill], // register skills alongside agents
chatModel: new ChatOpenAI({ model: 'gpt-5.4-mini' }),
scopeResolver,
});
// At runtime the support agent sees both skill *descriptions* in its prompt, and
// emits load_skill({ id: 'refund-policy' }) only when it actually needs the full text.Skills compose with multi-agent: give each specialized child only the skills it
needs (developer → coding-conventions, researcher → search-playbook), so
every agent's prompt carries just its own relevant knowledge.
Persistence & observability
Persist conversations and task events with the bundled stores
(InMemoryConvStore / FileConvStore, InMemoryTaskEventStore /
FileTaskEventStore), and observe the run via framework hooks (HookEmitter:
agent start/end, spawn, tool-call/result, errors).
Exports
defineAgent/AgentDef,defineSkill/SkillDefAgentRegistry,SkillRegistryAgentFramework,createAgentFramework,RunHandle,RunOptionsRouter,BackgroundDispatcher,HookEmitter+ hook types- Persistence:
InMemoryConvStore,InMemoryTaskEventStore,FileConvStore,FileTaskEventStore
Full type definitions ship with the package.
License
MIT © MorphixAI
