All skills
jwynia avatar

/mastra-hono

@99a8797
by J Wyniajwynia/agent-skills160 stars
20

Develop AI agents, tools, and workflows with Mastra v1 Beta and Hono servers. This skill should be used when creating Mastra agents, defining tools with Zod schemas, building workflows with step data flow, setting up Hono API servers with Mastra adapters, or implementing agent networks. Keywords: mastra, hono, agent, tool, workflow, AI, LLM, typescript, API, MCP.

Use this Skill: https://skilld.dev/gh/jwynia/agent-skills/mastra-hono

This session only. Nothing lands on disk.

referencescontext-network-memory.md

≈4.1k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Context Network Memory Patterns

Guide to integrating context networks across agent knowledge, conversation memory, and developer documentation.

Overview

Context networks provide a structured approach to organizing information at three levels:

  1. Agent Knowledge (RAG) - Facts and documents agents can retrieve
  2. Conversation Memory - Thread-based context and insights
  3. Developer Documentation - Project knowledge that informs agent behavior

This integration creates a unified knowledge layer where information flows between all three levels.

Level 1: Agent Knowledge as Context Network

Organizing Knowledge with Atomic Notes

// Knowledge as atomic, interconnected notes
interface KnowledgeNode {
  id: string;
  title: string;
  content: string;
  type: "fact" | "concept" | "procedure" | "decision";
  connections: string[];  // IDs of related nodes
  metadata: {
    source: string;
    createdAt: string;
    confidence: number;
  };
}

// Example knowledge nodes
const knowledgeBase: KnowledgeNode[] = [
  {
    id: "api-auth",
    title: "API Authentication",
    content: "The API uses Bearer token authentication...",
    type: "procedure",
    connections: ["api-endpoints", "security-policies"],
    metadata: { source: "docs", createdAt: "2024-01-15", confidence: 1.0 },
  },
  {
    id: "api-endpoints",
    title: "API Endpoints",
    content: "Available endpoints include /users, /orders, /products...",
    type: "concept",
    connections: ["api-auth", "rate-limits"],
    metadata: { source: "docs", createdAt: "2024-01-15", confidence: 1.0 },
  },
];

Indexing with Relationship Metadata

// Index knowledge nodes with connection information
async function indexKnowledgeNetwork(nodes: KnowledgeNode[]) {
  const embeddings = await embedMany({
    model: openai.embedding("text-embedding-3-small"),
    values: nodes.map(n => `${n.title}\n\n${n.content}`),
  });

  await mastra.vectors?.default.upsert({
    indexName: "knowledge-network",
    vectors: nodes.map((node, i) => ({
      id: node.id,
      vector: embeddings.embeddings[i],
      metadata: {
        title: node.title,
        content: node.content,
        type: node.type,
        connections: node.connections,
        ...node.metadata,
      },
    })),
  });
}

Graph-Aware Retrieval

export const contextNetworkSearch = createTool({
  id: "context-network-search",
  description: "Search knowledge network with relationship expansion",
  inputSchema: z.object({
    query: z.string(),
    expandConnections: z.boolean().optional().default(true),
    maxDepth: z.number().optional().default(1),
  }),
  execute: async (input, context) => {
    const { query, expandConnections, maxDepth } = input;
    const { mastra } = context;

    // Initial semantic search
    const { embedding } = await embed({
      model: openai.embedding("text-embedding-3-small"),
      value: query,
    });

    const directResults = await mastra?.vectors?.default.query({
      indexName: "knowledge-network",
      queryVector: embedding,
      topK: 5,
    });

    if (!expandConnections) {
      return { nodes: directResults };
    }

    // Expand connections
    const expanded = new Map();
    const queue = directResults?.map(r => ({ node: r, depth: 0 })) || [];

    while (queue.length > 0) {
      const { node, depth } = queue.shift()!;

      if (expanded.has(node.id) || depth > maxDepth) continue;
      expanded.set(node.id, node);

      // Fetch connected nodes
      if (depth < maxDepth && node.metadata.connections) {
        for (const connId of node.metadata.connections) {
          const connected = await mastra?.vectors?.default.get({
            indexName: "knowledge-network",
            id: connId,
          });
          if (connected) {
            queue.push({ node: connected, depth: depth + 1 });
          }
        }
      }
    }

    return {
      nodes: Array.from(expanded.values()),
      connections: directResults?.flatMap(r => r.metadata.connections || []),
    };
  },
});

Level 2: Conversation Memory as Context Network

Thread Organization Patterns

// Threads organized by context type
interface ThreadContext {
  threadId: string;
  contextType: "support" | "research" | "planning" | "general";
  topic: string;
  connections: string[];  // Related threads
  insights: ConversationInsight[];
}

interface ConversationInsight {
  id: string;
  type: "preference" | "fact" | "decision" | "question";
  content: string;
  extractedFrom: string;  // Message ID
  confidence: number;
}

Extracting Insights from Conversations

const insightExtractor = createStep({
  id: "extract-insights",
  execute: async ({ inputData, mastra }) => {
    const { threadId, messages } = inputData;

    // Use LLM to extract insights
    const extractor = new Agent({
      name: "insight-extractor",
      model: openai("gpt-4o-mini"),
      instructions: `Extract key insights from conversations.
        Categories:
        - preference: User preferences (e.g., "prefers dark mode")
        - fact: Facts about user/context (e.g., "works at TechCorp")
        - decision: Decisions made (e.g., "chose Plan B")
        - question: Unanswered questions`,
    });

    const conversation = messages.map(m => `${m.role}: ${m.content}`).join("\n");

    const insights = await extractor.generate(conversation, {
      output: z.object({
        insights: z.array(z.object({
          type: z.enum(["preference", "fact", "decision", "question"]),
          content: z.string(),
          confidence: z.number(),
        })),
      }),
    });

    // Store insights in knowledge network
    for (const insight of insights.object.insights) {
      await mastra?.vectors?.default.upsert({
        indexName: "conversation-insights",
        vectors: [{
          id: `${threadId}-${Date.now()}`,
          vector: await getEmbedding(insight.content),
          metadata: {
            ...insight,
            threadId,
            extractedAt: new Date().toISOString(),
          },
        }],
      });
    }

    return { insights: insights.object.insights };
  },
});

Cross-Session Context

export const retrieveUserContext = createTool({
  id: "retrieve-user-context",
  description: "Retrieve relevant context from user's conversation history",
  inputSchema: z.object({
    userId: z.string(),
    currentQuery: z.string(),
  }),
  execute: async (input, context) => {
    const { userId, currentQuery } = input;
    const { mastra } = context;

    // Get insights relevant to current query
    const { embedding } = await embed({
      model: openai.embedding("text-embedding-3-small"),
      value: currentQuery,
    });

    const relevantInsights = await mastra?.vectors?.default.query({
      indexName: "conversation-insights",
      queryVector: embedding,
      topK: 10,
      filter: { userId },
    });

    // Get recent conversation context
    const recentThreads = await mastra?.storage?.listThreads({
      resourceId: userId,
      limit: 5,
    });

    return {
      insights: relevantInsights?.map(i => ({
        type: i.metadata.type,
        content: i.metadata.content,
        from: i.metadata.threadId,
      })),
      recentTopics: recentThreads?.map(t => t.metadata?.topic),
    };
  },
});

Memory Consolidation to Knowledge

const consolidateToKnowledge = async (threadId: string, userId: string) => {
  const insights = await mastra.vectors?.default.query({
    indexName: "conversation-insights",
    filter: { threadId },
    topK: 100,
  });

  // High-confidence insights become permanent knowledge
  const permanentInsights = insights?.filter(i => i.metadata.confidence > 0.8);

  for (const insight of permanentInsights || []) {
    await mastra.vectors?.default.upsert({
      indexName: "user-knowledge",
      vectors: [{
        id: `${userId}-${insight.id}`,
        vector: insight.vector,
        metadata: {
          userId,
          content: insight.metadata.content,
          type: insight.metadata.type,
          source: "conversation",
          originalThread: threadId,
          consolidatedAt: new Date().toISOString(),
        },
      }],
    });
  }

  return { consolidated: permanentInsights?.length || 0 };
};

Level 3: Developer Documentation as Context

Project Context Network

// Structure mirrors .context-network.md
interface ProjectContext {
  architecture: {
    decisions: ArchitectureDecision[];
    patterns: Pattern[];
    constraints: Constraint[];
  };
  agents: {
    [agentName: string]: AgentContext;
  };
  tasks: {
    completed: TaskRecord[];
    inProgress: TaskRecord[];
  };
}

interface ArchitectureDecision {
  id: string;
  title: string;
  context: string;
  decision: string;
  consequences: string[];
  date: string;
  status: "active" | "superseded";
}

Agent Self-Documentation

// Agent can query its own documentation
export const selfDocsTool = createTool({
  id: "query-my-docs",
  description: "Query documentation about this agent's capabilities and constraints",
  inputSchema: z.object({
    query: z.string().describe("What to look up about my capabilities"),
  }),
  execute: async (input, context) => {
    const { query } = input;
    const { runtimeContext, mastra } = context;

    const agentName = runtimeContext.get("current-agent");

    // Search project context network
    const { embedding } = await embed({
      model: openai.embedding("text-embedding-3-small"),
      value: query,
    });

    const docs = await mastra?.vectors?.default.query({
      indexName: "project-context",
      queryVector: embedding,
      filter: {
        $or: [
          { type: "agent-docs", agentName },
          { type: "architecture-decision" },
          { type: "project-constraint" },
        ],
      },
      topK: 5,
    });

    return {
      capabilities: docs?.filter(d => d.metadata.type === "agent-docs"),
      relevantDecisions: docs?.filter(d => d.metadata.type === "architecture-decision"),
      constraints: docs?.filter(d => d.metadata.type === "project-constraint"),
    };
  },
});

Decision Record Integration

// Decisions from context network inform agent behavior
const decisionAwareAgent = new Agent({
  name: "decision-aware-agent",
  instructions: async ({ runtimeContext, mastra }) => {
    // Fetch relevant architectural decisions
    const decisions = await mastra?.vectors?.default.query({
      indexName: "project-context",
      filter: { type: "architecture-decision", status: "active" },
      topK: 10,
    });

    const decisionContext = decisions
      ?.map(d => `- ${d.metadata.title}: ${d.metadata.decision}`)
      .join("\n");

    return `You are a development assistant.

Respect these architectural decisions:
${decisionContext}

When in doubt about approaches, query the project documentation.`;
  },
  model: openai("gpt-4o-mini"),
  tools: { selfDocsTool },
});

Cross-Layer Integration

Unified Query Tool

export const unifiedContextSearch = createTool({
  id: "unified-context-search",
  description: "Search across all context layers: knowledge, memory, and docs",
  inputSchema: z.object({
    query: z.string(),
    layers: z.array(z.enum(["knowledge", "memory", "docs"])).optional(),
  }),
  execute: async (input, context) => {
    const { query, layers = ["knowledge", "memory", "docs"] } = input;
    const { mastra, runtimeContext } = context;

    const { embedding } = await embed({
      model: openai.embedding("text-embedding-3-small"),
      value: query,
    });

    const results: Record<string, any[]> = {};

    if (layers.includes("knowledge")) {
      results.knowledge = await mastra?.vectors?.default.query({
        indexName: "knowledge-network",
        queryVector: embedding,
        topK: 5,
      }) || [];
    }

    if (layers.includes("memory")) {
      const userId = runtimeContext.get("user-id");
      results.memory = await mastra?.vectors?.default.query({
        indexName: "conversation-insights",
        queryVector: embedding,
        filter: userId ? { userId } : undefined,
        topK: 5,
      }) || [];
    }

    if (layers.includes("docs")) {
      results.docs = await mastra?.vectors?.default.query({
        indexName: "project-context",
        queryVector: embedding,
        topK: 5,
      }) || [];
    }

    return results;
  },
});

Feedback Loops

// Conversation insights update knowledge
const feedbackLoop = createWorkflow({
  id: "context-feedback-loop",
  inputSchema: z.object({
    threadId: z.string(),
    userId: z.string(),
  }),
  outputSchema: z.object({ updated: z.number() }),
})
  .then(createStep({
    id: "extract-insights",
    execute: async ({ inputData, mastra }) => {
      // Extract new insights from conversation
      const messages = await mastra?.storage?.getMessages({
        threadId: inputData.threadId,
        limit: 50,
      });

      // ... insight extraction logic
      return { insights: extractedInsights };
    },
  }))
  .then(createStep({
    id: "validate-insights",
    execute: async ({ inputData }) => {
      // Filter high-confidence insights
      return {
        validInsights: inputData.insights.filter(i => i.confidence > 0.7),
      };
    },
  }))
  .then(createStep({
    id: "update-knowledge",
    execute: async ({ inputData, mastra }) => {
      // Update knowledge network
      let updated = 0;
      for (const insight of inputData.validInsights) {
        // Check if this updates existing knowledge
        const existing = await mastra?.vectors?.default.query({
          indexName: "knowledge-network",
          queryVector: await getEmbedding(insight.content),
          topK: 1,
          scoreThreshold: 0.95,
        });

        if (existing?.length) {
          // Update existing node
          await updateKnowledgeNode(existing[0].id, insight);
        } else {
          // Create new node
          await createKnowledgeNode(insight);
        }
        updated++;
      }
      return { updated };
    },
  }))
  .commit();

Developer Decisions Propagate to Agents

// When a new architectural decision is made
async function recordDecision(decision: ArchitectureDecision) {
  // 1. Store in project context
  await mastra.vectors?.default.upsert({
    indexName: "project-context",
    vectors: [{
      id: decision.id,
      vector: await getEmbedding(`${decision.title} ${decision.decision}`),
      metadata: {
        type: "architecture-decision",
        ...decision,
      },
    }],
  });

  // 2. Update affected agent instructions
  for (const agentName of getAffectedAgents(decision)) {
    await refreshAgentInstructions(agentName);
  }

  // 3. Notify relevant conversation threads
  const affectedThreads = await findAffectedThreads(decision);
  for (const thread of affectedThreads) {
    await mastra.storage?.addMessage({
      threadId: thread.id,
      role: "system",
      content: `[CONTEXT UPDATE] New architectural decision may affect this conversation: ${decision.title}`,
    });
  }
}

Best Practices

1. Atomic Knowledge Nodes

Keep knowledge nodes small and focused:

  • One concept per node
  • 100-300 words maximum
  • Clear connections to related nodes

2. Explicit Connections

Always define relationships:

  • relatedTo: Conceptual similarity
  • dependsOn: Prerequisite knowledge
  • supersedes: Updated information
  • conflictsWith: Contradictory information

3. Source Tracking

Always track where information came from:

  • source: "docs" - Official documentation
  • source: "conversation" - Extracted from user
  • source: "decision" - Architectural decision
  • source: "inferred" - AI-generated connection

4. Confidence Scoring

Track reliability of information:

  • 1.0: Verified fact
  • 0.8+: High confidence
  • 0.5-0.8: Moderate confidence
  • <0.5: Speculative

5. Regular Maintenance

Schedule maintenance workflows:

  • Consolidate conversation insights weekly
  • Validate knowledge connections monthly
  • Archive superseded decisions quarterly

Source: SKILL.md on GitHub

2 warnings16d5 checks · Risk SAFE
  • Gen Agent Trust Hub16d

    This skill provides a comprehensive developer toolkit for building AI agents and workflows with Mastra v1 Beta and Hono servers. It includes scaffolding scripts, code templates, and detailed documentation on best practices for agent orchestration and data flow. All external dependencies are from well-known technology organizations and the code patterns align with standard software development practices.

  • Socket16d

    1 alert: gptAnomaly

  • Snyk16d

    Risk: LOW · No issues

  • Runlayer7mo

    22/22 files flagged

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at 99a8797. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 months ago.

Dormantupdated 8 months ago
compatibility
Node.js 22.13.0+ required for v1 Beta
Other metadata
metadata
{
  "author": "agent-skills",
  "version": "1.0",
  "type": "utility",
  "mode": "assistive",
  "domain": "development"
}

README badge

README badge for jwynia/agent-skills/mastra-hono