Skip to content

Implementations

Edge Connector Development

Implementations are the code files you write to handle EDGE tool executions. When an agent calls a tool with execution type EDGE, the request is routed to the Edge Connector, which loads the corresponding implementation, executes it with the provided parameters, and returns a structured result. This page explains how to create, test, package, and deploy custom implementations.

Every EDGE tool in the nara registry has a defined set of input parameters (a schema) and a result schema. An implementation is a JavaScript or TypeScript file that exports a handler function matching those schemas. The handler receives the parsed parameters and an execution context, performs the required work (calling an API, querying a database, running a system command), and returns a result object.

Implementations are organized as individual files in a tools/ directory, one file per tool. This structure allows the Edge Connector to bundle, version, and distribute each tool independently.

Custom implementations follow a standard directory layout:

custom-implementations/
package.json # Dependencies for your tool code
tsconfig.json # TypeScript configuration (if using TypeScript)
tools/ # One file per tool
getSystemInfo.ts # Implementation for the getSystemInfo tool
restartService.ts # Implementation for the restartService tool
queryDatabase.ref.json # Reference to server-hosted version (no local source)
dist/ # Compiled output (auto-generated during build)
index.js # Auto-generated index that exports all tools
tools/
getSystemInfo.js # Compiled tool
restartService.js # Compiled tool

The fastest way to create a new implementation is to use the generate command. It connects to the nara platform server, fetches the tool’s schemas, and generates a properly typed TypeScript file.

  1. Ensure you are authenticated:

    Terminal window
    edge-connector auth --browser
  2. Generate the implementation:

    Terminal window
    edge-connector generate -l typescript -t getSystemInfo -o ./custom-implementations
  3. The CLI creates a TypeScript file at ./custom-implementations/tools/getSystemInfo.ts with:

    • Typed input parameters derived from the tool’s schema
    • A result type matching the tool’s result schema
    • A handler function stub with error handling scaffolding
    • An execution context parameter with user and organization information
  4. Open the file in your editor and implement the logic.

You can also run edge-connector generate --interactive to browse available EDGE tools and select one from a list.

Here is a complete example of a TypeScript tool implementation:

type GetSystemInfoParams = {
includeNetwork?: boolean
}
type GetSystemInfoResult = {
hostname: string
platform: string
arch: string
uptime: number
memory: {
total: number
free: number
used: number
}
network?: {
interfaces: string[]
}
}
export default async function getSystemInfo(
params: GetSystemInfoParams,
_context: unknown
): Promise<{
status: 'success' | 'error'
result?: GetSystemInfoResult
error?: { message: string; isRetryable: boolean }
}> {
try {
const os = await import('node:os')
const result: GetSystemInfoResult = {
hostname: os.hostname(),
platform: os.platform(),
arch: os.arch(),
uptime: os.uptime(),
memory: {
total: os.totalmem(),
free: os.freemem(),
used: os.totalmem() - os.freemem(),
},
}
if (params.includeNetwork) {
const interfaces = os.networkInterfaces()
result.network = {
interfaces: Object.keys(interfaces),
}
}
return { status: 'success', result }
} catch (err) {
return {
status: 'error',
error: {
message: err instanceof Error ? err.message : 'Unknown error',
isRetryable: false,
},
}
}
}

Every implementation must satisfy these requirements:

RequirementDescription
Default exportThe file must export a default async function as the handler
ParametersThe first argument receives the parsed tool parameters (matching the tool’s schema)
ContextThe second argument receives execution context data when request-scoped metadata is available
Return valueMust return an object with status ('success' or 'error'), and either a result or error field
Error structureError objects must include message (string) and isRetryable (boolean)
File namingThe file name (without extension) must match the tool’s registered name

Test your implementations locally using the run command before uploading to production.

  1. Ensure the nara platform server is running.

  2. Run the Edge Connector in test mode:

    Terminal window
    edge-connector run --implementations ./custom-implementations --url ws://localhost:3001
  3. Open the nara webapp and start a conversation with an agent that has your EDGE tool assigned.

  4. Trigger the tool (e.g., ask the agent to run system diagnostics). The tool execution request flows through the platform to your local Edge Connector.

  5. Check the terminal output for execution logs and results.

When your implementation is ready, package it into a distributable bundle.

Terminal window
edge-connector package -i ./custom-implementations -o ./artifacts

What happens during packaging:

  1. The CLI discovers all tool source files in tools/ (.ts, .js, .mjs, .cjs).

  2. Each tool is compiled individually using esbuild into dist/tools/.

  3. An auto-generated dist/index.js is created that exports all tool handlers.

  4. Any .ref.json reference files are included in the manifest (for tools using server-hosted versions).

  5. A manifest (manifest.json) is created with the organization ID, language, tool entries (name, checksum, size), references, build timestamp, and overall checksum.

  6. Everything is archived into a .tgz file in the output directory.

If you have a package.json in your implementations directory with dependencies, the CLI automatically runs pnpm install if node_modules/ does not exist.

TypeScript compilation is handled automatically by esbuild during the packaging step. Each tool file is bundled individually, producing a self-contained .js file per tool. This means:

  • Tools are isolated from each other at the bundle level.
  • Dependencies are inlined (no node_modules needed in the bundle).
  • The build is fast — esbuild processes files in milliseconds.

To skip the build step (if you have already compiled manually), use --no-build:

Terminal window
edge-connector package --no-build

Handle errors gracefully

Always wrap your implementation logic in try/catch. Return structured error objects with descriptive messages. Set isRetryable: true for transient errors (network timeouts, temporary unavailability) and isRetryable: false for permanent failures (invalid input, missing resource).

Return structured results

Match the tool’s result schema exactly. The agent receives the result object and uses it to formulate responses. Include all fields the schema expects, even if some are null or empty.

Respect timeouts

Tool executions have a timeout enforced by the platform server. Keep implementations fast and responsive. For long-running operations, consider breaking them into smaller steps or returning a status that the agent can poll.

Keep secrets secure

Never hardcode credentials in implementation files. Use environment variables, secrets managers, or the Edge Connector’s configuration to inject sensitive values at runtime. Tool bundles are stored on the platform server.