← Back to Docs

This guide has moved to the Wiki. Go to Code Agents Guide →

GitHub Code Agents

Write TypeScript agents in your own GitHub repository and deploy them to OpenShopFloor with one click.

What are Code Agents?

Code Agents let you write custom TypeScript functions that have full access to all 118 MCP tools, an LLM for analysis, and persistent key-value storage. Your code runs in a secure V8 sandbox with no file system or network access — all external calls go through the SDK.

Quick Start

  1. Connect GitHub — Go to Settings → GitHub and connect your account.
  2. Create a repository with two files:
    osf-agent.yaml
    name: My First Agent
    description: Analyzes OEE data
    icon: "📊"
    entry: src/main.ts
    timeout: 60
    src/main.ts
    export default async function main(ctx) {
      // Call any MCP tool
      const oee = await ctx.mcp.call('factory_get_latest_oee');
      ctx.log('OEE data received');
    
      // Use LLM for analysis
      const analysis = await ctx.llm.chat(
        `Analyze this OEE data and suggest improvements: ${JSON.stringify(oee)}`
      );
      ctx.log(analysis);
    
      // Store results for later
      await ctx.storage.set('last_analysis', {
        timestamp: new Date().toISOString(),
        analysis,
      });
    
      return { analysis };
    }
  3. Deploy — Go to Agents → Deploy from GitHub, select your repo, and click Deploy.
  4. Run — Open your agent's detail page and click Run. Watch the output stream in real time.

The SDK Context (ctx)

Your main(ctx) function receives a context object with these modules:

ctx.mcp

MethodDescription
ctx.mcp.call(name, args?)Call any MCP tool. Returns parsed JSON result.
ctx.mcp.listTools()List all available MCP tools with descriptions.

ctx.llm

MethodDescription
ctx.llm.chat(prompt)Send a prompt to the LLM. Returns the text response.

ctx.storage

MethodDescription
ctx.storage.get(key)Read a stored value (scoped per agent + user).
ctx.storage.set(key, value)Store any JSON-serializable value.
ctx.storage.delete(key)Remove a stored value.

ctx.log

MethodDescription
ctx.log(message)Log a message to the live output terminal.

Using osf-ts in Flows (Multi-Output)

Code agents can also be used as osf-ts nodes inside Node-RED flows. The osf-ts node supports multi-output — configure 1 to 5 output ports and return an array to route different results to different downstream paths.

osf-ts node (2 outputs)
// Return an array — each element goes to a different output port
const oee = await ctx.mcp.call('factory_get_latest_oee');
const isGood = oee.oee_percent > 85;

return [
  isGood ? oee : null,     // Port 0: good OEE → continue
  !isGood ? oee : null,    // Port 1: bad OEE → alert path
];

When the node has 1 output (default), return a single value as usual. When configured with multiple outputs, return an array where each element maps to an output port. Use null to skip a port.

Manifest Reference (osf-agent.yaml)

FieldRequiredDefaultDescription
nameYesDisplay name of the agent
descriptionNoShort description shown in the UI
iconNo💻Emoji icon
entryNosrc/main.tsPath to the entry file
timeoutNo60Max execution time in seconds (max 300)

Auto-Sync via Webhooks

When you push to your repository, OpenShopFloor automatically re-syncs your agent. The platform fetches the latest osf-agent.yaml and entry file, re-bundles the code, and updates the deployment. You can also manually trigger a sync from the agent detail page.

Security & Limits

  • Code runs in an isolated V8 sandbox (isolated-vm) — no filesystem, no network, no require/import
  • Memory limit: 128 MB per execution
  • Timeout: configurable up to 300 seconds
  • Rate limit: 3 runs per minute
  • All MCP and storage calls are scoped to your user ID
  • GitHub tokens are encrypted with AES-256-GCM
  • Repository must be public (open source)

Examples

Machine Status Monitor

src/main.ts
export default async function main(ctx) {
  const machines = await ctx.mcp.call('factory_get_all_machines');
  const stopped = machines.filter(m => m.status === 'stopped');

  if (stopped.length > 0) {
    const report = await ctx.llm.chat(
      `These machines are stopped. Analyze possible causes: ${JSON.stringify(stopped)}`
    );
    ctx.log(`⚠ ${stopped.length} machines stopped`);
    ctx.log(report);
  } else {
    ctx.log('All machines running normally');
  }
}

Daily Quality Report

src/main.ts
export default async function main(ctx) {
  const defects = await ctx.mcp.call('factory_get_quality_notifications');
  const previous = await ctx.storage.get('last_defects');

  const report = await ctx.llm.chat(`
    Create a quality report comparing current defects with previous data.
    Current: ${JSON.stringify(defects)}
    Previous: ${JSON.stringify(previous)}
  `);

  await ctx.storage.set('last_defects', defects);
  ctx.log(report);
  return { report, defectCount: defects.length };
}

Multi-Output Router (osf-ts in Flows)

osf-ts node (3 outputs)
// Classify machines and route to 3 different paths
const machines = await ctx.mcp.call('factory_get_all_machines');

const running = machines.filter(m => m.status === 'running');
const idle = machines.filter(m => m.status === 'idle');
const stopped = machines.filter(m => m.status === 'stopped');

return [running, idle, stopped];
// Port 0 → running machines pipeline
// Port 1 → idle analysis
// Port 2 → stopped alert flow

This site uses a cookie to remember your preferences. Analytics are anonymous and cookie-free. Privacy Policy