Ikanos — FAQ¶
Welcome to the Ikanos FAQ! This guide answers common questions from developers who are learning, using, and contributing to Ikanos. For comprehensive technical details, see the Specification - Schema and Specification - Rules.
⛵ Getting Started¶
Q: What is Ikanos and why would I use it?¶
A: Ikanos is the first open-source platform for Spec-Driven Integration. Instead of writing boilerplate code to consume HTTP APIs and expose unified interfaces, you declare them in YAML. This enables: - API composability: Combine multiple APIs into a single capability - Format conversion: Convert between JSON, XML, Avro, Protobuf, CSV, TSV, PSV, HTML, Markdown, and YAML - AI-ready integration: Better context engineering for AI systems - Reduced API sprawl: Manage microservices and SaaS complexity
Use it when you need to integrate multiple APIs, standardize data formats, or expose simplified interfaces to AI agents.
Q: What skills do I need to create a capability?¶
A: You only need to know: - YAML syntax - the configuration language for capabilities - JSONPath - for extracting values from JSON responses - Mustache templates - for injecting parameters (optional, if using advanced features)
You don't need to write Java or other code unless you want to extend the framework itself.
Q: Is Ikanos a code generator or a runtime engine?¶
A: It's a runtime engine. Ikanos reads your YAML capability file at startup and immediately exposes HTTP or MCP interfaces, either through the Docker image or directly with ikanos serve. There's no compilation step - declare your capability, start the engine, and it works.
Q: Are there other tools that complement Ikanos?¶
A: Yes. Ikanos is part of Naftiko Fleet (Community Edition), which includes free complementary tools:
- Crafter — Naftiko VS Code extension with inline structure and rules validation while editing Ikanos capability files
- Warden — Backstage plugin to scaffold new capabilities and catalog them from CNCF Backstage
- Skipper — Kubernetes operator to deploy and operate capabilities on Kubernetes
Installation & Setup¶
Q: How do I install Ikanos?¶
A: There are two ways:
- Docker (recommended)
bash docker pull ghcr.io/naftiko/ikanos:{{RELEASE_TAG}} docker run -p 8081:8081 -v /path/to/capability.yaml:/app/capability.yaml ghcr.io/naftiko/ikanos:{{RELEASE_TAG}} serve /app/capability.yaml
If your capability is mounted at /app/ikanos.yaml, you can rely on the image default command and omit serve entirely.
- CLI tool (for configuration, validation, and local execution) Download the binary for macOS, Linux, or Windows
See the Installation guide for detailed setup instructions.
Q: How do I run a capability locally without Docker?¶
A: Use the CLI serve command:
ikanos serve path/to/capability.yaml
# Or, if the file is named ikanos.yaml in the current directory
ikanos serve
This starts the same runtime path as the Docker image, but directly on your machine, and stops cleanly with Ctrl-C.
Q: How do I validate my capability file before running it?¶
A: Use the CLI validation command:
ikanos validate path/to/capability.yaml
ikanos validate path/to/capability.yaml {{RELEASE_TAG}} # Specify schema version
This checks your YAML against the Ikanos schema and reports any errors.
Q: Which version of the schema should I use?¶
A: Use the current framework schema version: {{RELEASE_TAG}}.
Set it in your YAML:
🧭 Core Concepts¶
Q: What are "exposes" and "consumes"?¶
A: These are the two essential parts of every capability:
- Exposes - What your capability provides to callers (REST, MCP or SKILL server)
- Consumes - What HTTP APIs your capability uses internally
Example: A capability that consumes the Notion API and GitHub API, then exposes them as a single unified REST endpoint or MCP tool.
Q: What's the difference between REST and MCP exposure?¶
A:
| Feature | REST | MCP |
|---|---|---|
| Protocol | REpresentational State Transfer (JSON-HTTP) | Model Context Protocol (JSON-RPC) |
| Best for | General-purpose integrations, web apps | AI agent-native integrations |
| Tool discovery | Manual or via OpenAPI | Automatic via MCP protocol |
| Configuration | type: "rest" with resources/operations |
type: "mcp" with tools |
| Default transport | HTTP | stdio or HTTP (streamable) |
Use REST for traditional REST clients, web applications, or when you want standard HTTP semantics.
Use MCP when exposing capabilities to AI agents or Claude.
Q: What is a "namespace"?¶
A: A namespace is a unique identifier for a consumed or exposed source, used for routing and references.
- In consumes:
namespace: githubmeans "this is the GitHub API I'm consuming" - In exposes:
namespace: appmeans "my exposed API is calledapp" - In steps:
call: github.get-userroutes to the consumedgithubnamespace
Namespaces must be unique within their scope (all consumed namespaces must differ, all exposed namespaces must differ).
Q: What are "steps" and when do I use them?¶
A: Steps enable multi-step orchestration - calling multiple APIs in sequence and combining their results.
Simple mode (direct call):
operations:
- method: GET
call: github.get-user # Call one consumed operation directly
with:
username: "{{github_username}}"
Orchestrated mode (multi-step):
operations:
- name: complex-operation
method: GET
steps:
- type: call
name: step1
call: github.list-users
- type: call
name: step2
call: github.get-user
with:
username: $step1.result # Use output from step1
mappings:
- target: output_field
value: $.step2.userId
Use steps when your capability needs to combine data from multiple sources or perform lookups.
Q: What's the difference between "call" and "lookup" steps?¶
A:
callsteps: Execute a consumed operation (HTTP request)lookupsteps: Search through a previous step's output for matching records
Example: Call an API to list all users, then lookup which one matches a given email:
steps:
- type: call
name: list-all-users
call: hr.list-employees
- type: lookup
name: find-user-by-email
index: list-all-users
match: email
lookupValue: "{{email_to_find}}"
outputParameters:
- fullName
- department
🧱 Aggregates & Reuse (DDD-inspired)¶
Q: What are aggregates and why should I use them?¶
A: Aggregates are domain-centric building blocks inspired by Domain-Driven Design (DDD). An aggregate groups reusable flows under a namespace that represents a coherent domain concept — similar to how a DDD Aggregate Root encapsulates a cluster of related entities.
Use aggregates when: - The same domain operation (e.g., "get forecast") is exposed through multiple adapters (REST and MCP). - You want to maintain a single source of truth for flow definitions (name, description, call chain, parameters). - You want transport-neutral behavioral metadata (semantics) that auto-maps to adapter-specific features.
capability:
aggregates: # alpha3 — keyed map by namespace
forecast:
display: Weather Forecast
flows: # alpha3 — keyed map by flow name
get-forecast:
description: Retrieve weather forecast for a city
semantics:
safe: true
idempotent: true
call: weather-api.get-forecast
inputParameters: # alpha3 — keyed map
city:
type: string
description: City name
outputParameters:
- type: object
mapping: $.forecast
Q: How does ref work to reference an aggregate flow?¶
A: MCP tools and REST operations can reference an aggregate flow using ref: {namespace}.{flow-name}. The engine merges inherited fields from the flow — you only specify what's different at the adapter level.
exposes:
- type: mcp
tools: # alpha3 — keyed map; key IS the tool name
get-forecast:
ref: forecast.get-forecast # inherits description, call, params
weather-lookup:
ref: forecast.get-forecast # override description for MCP context
description: Look up weather for a city (MCP-optimized)
- type: rest
resources: # alpha3 — keyed map
forecast:
path: /forecast
Merge rules:
- Explicit fields on the tool/operation override inherited fields from the flow.
- Fields not set on the tool/operation are inherited from the flow.
- name and description are optional when using ref — they default to the flow's values.
Q: How do semantics map to MCP tool hints?¶
A: Aggregate flows can declare transport-neutral semantics (safe, idempotent, cacheable). When exposed as MCP tools, the engine automatically derives MCP tool hints:
| Semantics | MCP Hint | Rule |
|---|---|---|
safe: true |
readOnly: true, destructive: false |
Safe operations don't modify state |
safe: false |
readOnly: false, destructive: true |
Unsafe operations may modify state |
idempotent |
idempotent |
Passed through directly |
cacheable |
(not mapped) | No MCP equivalent |
| (not derived) | openWorld |
Must be set explicitly on the MCP tool |
Explicit hints on the MCP tool override derived values, so you can fine-tune behavior per-tool.
📦 Importing & Modularization¶
Q: Why was location renamed to from in consumes imports?¶
A: The binds section already uses location to mean "runtime variable source" — where to fetch secrets at runtime (e.g., file://./secrets.env, vault://app/prod). Reusing location as an import keyword on any section would create semantic ambiguity: does location mean "where to get this entry's definition" or "where to fetch this entry's runtime data"?
from is unambiguous, short, and idiomatic (inspired by ES module syntax: import x from './foo'). It reads naturally in YAML: "this entry comes from another file." The rename was a hard break (no alias) because the project is in alpha.
Q: Can I import bindings from another file?¶
A: Yes. The binds section supports the same from/import/as directive as consumes, exposes, and aggregates:
binds:
- from: "./shared/secrets.binds.yml"
import: api-secrets
- from: "./shared/secrets.binds.yml"
import: db-secrets
as: database-secrets
The imported binding keeps its own location (runtime variable source) — from is consumed by the resolver at parse time and does not appear in the materialized entry.
Q: Why are standalone files leaves — can I import consumes from inside an aggregates file?¶
A: Not in 1.0. Every standalone file (.consumes.yml, .exposes.yml, .aggregates.yml, .binds.yml) is a leaf in the import graph. Only capability documents may import. This is the strictest possible design, chosen for three reasons:
- Symmetry. Letting only aggregates import consumes would re-introduce context-dependent rules the unified mechanism was built to remove.
- No evidence yet. A capability that uses a shared aggregates file simply writes two import directives — one for aggregates, one for consumes. That's explicit and trivial.
- Strictly additive to add later. Transitive imports need cycle detection, layer enforcement, and namespace merging. Carrying that in 1.0 before there is demand is YAGNI. If needed, the change is purely additive.
See the Importing Guide for the full design rationale.
🔩 Configuration & Parameters¶
Q: How do I inject input parameters into a consumed operation?¶
A: Use the with injector in your exposed operation:
Simple mode:
operations:
- method: GET
call: github.get-user
with:
username: "{{github_username}}" # From binds
accept: "application/json" # Static value
Orchestrated mode (steps):
The with object maps consumed operation parameter names to:
- Variable references like {{VARIABLE_NAME}} injected from binds
- Static strings or numbers - literal values
Q: How do I extract values from API responses (output parameters)?¶
A: Use JsonPath expressions in the value field of outputParameters:
consumes:
- resources:
- operations:
- outputParameters:
- name: userId
type: string
value: $.id # Top-level field
- name: email
type: string
value: $.contact.email # Nested field
- name: allNames
type: array
value: $.users[*].name # Array extraction
Common JsonPath patterns:
- $.fieldName - access a field
- $.users[0].name - access array element
- $.users[*].name - extract all .name values from array
- $.data.user.email - nested path
Q: What are "mappings" and when do I use them?¶
A: Mappings connect step outputs to exposed operation outputs in multi-step orchestrations.
steps:
- type: call
name: fetch-db
call: notion.get-database
- type: call
name: query-db
call: notion.query-database
mappings:
- target: database_name # Exposed output parameter
value: $.fetch-db.dbName # From first step's output
- target: row_count
value: $.query-db.resultCount # From second step
outputParameters:
database_name:
type: string
row_count:
type: number
Mappings tell Ikanos how to wire step outputs to your final response.
🔄 OpenAPI Interoperability¶
Q: Can I bootstrap a capability from an existing OpenAPI specification?¶
A: Yes. Use the CLI import command:
This parses an OAS 3.0 or 3.1 document and generates a Ikanos capability YAML with a pre-filledconsumes HTTP adapter — including authentication, resources, operations, input parameters, and output parameters.
Q: Can I export my REST adapter as an OpenAPI document?¶
A: Yes. Use the CLI export command:
ikanos export openapi capability.yaml
ikanos export openapi capability.yaml --spec-version 3.1 -f json
exposes adapter.
Q: Which OpenAPI versions are supported?¶
A: OAS 3.0 and 3.1 are fully supported for both import and export. OAS 3.2 support is deferred until the upstream Java libraries (swagger-parser, swagger-core) add it.
Q: What if my capability has multiple REST adapters?¶
A: Use the --adapter option to target a specific namespace:
🗝️ Authentication & Security¶
Q: How do I authenticate to external APIs?¶
A: Add an authentication block to your consumes section:
consumes:
- type: http
namespace: github
baseUri: https://api.github.com
authentication:
type: bearer
token: "{{GITHUB_TOKEN}}" # Use token from binds
Supported authentication types:
- bearer - Bearer token
- basic - Username/password
- apikey - Header or query parameter API key
- digest - HTTP Digest authentication
Q: How do I manage secrets like API tokens?¶
A: Use binds to declare variables that are injected at runtime:
binds:
- namespace: secrets
keys:
GITHUB_TOKEN: GITHUB_TOKEN # Maps env var to template variable
NOTION_TOKEN: NOTION_TOKEN
consumes:
- namespace: github
authentication:
type: bearer
token: "{{GITHUB_TOKEN}}" # Use the injected variable
- namespace: notion
authentication:
type: bearer
token: "{{NOTION_TOKEN}}"
At runtime, provide environment variables:
⚠️ Security note: Use runtime injection (omit
location) in production. Never commit secrets to your repository.
Q: Can I authenticate to exposed endpoints (REST/MCP)?¶
A: Yes, add authentication to your exposes block:
exposes:
- type: rest
port: 8081
namespace: my-api
authentication:
type: apikey
in: header
name: X-Api-Key
value: "{{api_key}}"
resources:
- path: /data
description: Protected data endpoint
Supported authentication types for exposed endpoints:
- apikey - API key via header or query parameter
- bearer - Bearer token validation
- basic - Username/password via HTTP Basic Auth
Q: Can I send complex request bodies (JSON, XML, etc.)?¶
A: Yes, use the body field for request bodies:
Body types:
- json - JSON object or string
- text, xml, sparql - Plain text payloads
- formUrlEncoded - URL-encoded form
- multipartForm - Multipart file upload
🗺️ REST API Design¶
Q: How do I define resource paths with parameters?¶
A: Use path parameters with curly braces:
exposes:
- resources:
- path: /users/{userId}/projects/{projectId}
description: Get a specific project for a user
inputParameters:
- name: userId
in: path
type: string
description: The user ID
- name: projectId
in: path
type: string
description: The project ID
Callers access it as: GET /users/123/projects/456
Q: How do I support query parameters and headers?¶
A: Use in field in inputParameters:
inputParameters:
- name: filter
in: query
type: string
description: Filter results
- name: Authorization
in: header
type: string
description: Auth header
- name: X-Custom
in: header
type: string
description: Custom header
Callers send: GET /endpoint?filter=value with custom headers.
Q: How do forward proxies work?¶
A: Use forward to pass requests through to a consumed API without transformation:
exposes:
- resources:
- path: /github/{path}
description: Pass-through proxy to GitHub API
forward:
targetNamespace: github
trustedHeaders:
- Authorization
- Accept
This forwards GET /github/repos/owner/name to GitHub's /repos/owner/name.
Trusted headers must be explicitly listed for security.
📡 MCP-Specific¶
Q: How do I expose a capability as an MCP tool?¶
A: Use type: mcp in exposes instead of type: rest:
exposes:
- type: mcp
address: localhost
port: 9091
namespace: my-mcp
description: My MCP server
tools:
- name: query-database
description: Query the database
call: notion.query-db
with:
db_id: "fixed-db-id"
outputParameters:
- type: array
mapping: $.results
Q: What's the difference between HTTP and Stdio MCP transports?¶
A:
| Transport | Use Case | Setup |
|---|---|---|
| HTTP | Streamable HTTP transport, integrates with existing infrastructure | Specify address and port |
| Stdio | Direct process communication, native integration with Claude Desktop | No address/port needed |
For Claude integration, Stdio is typically preferred. HTTP is useful for remote or containerized deployments.
Q: How do I expose MCP resources and prompts?¶
A: Add resources and prompts sections to your MCP server:
exposes:
- type: mcp
resources:
- uri: file:///docs/guide.md
name: User Guide
description: API usage guide
prompts:
- name: analyze-code
description: Analyze code snippet
template: "Analyze this code:\n{{code}}"
MCP clients can then discover and use these resources dynamically.
Q: Can I create MCP tools that return static mock data?¶
A: Yes, starting in version 1.0.0 Alpha 2. Define outputParameters with value fields and omit call and steps. The tool serves a fixed JSON response — no consumes block is needed. Values can be static strings or Mustache templates resolved against input parameters:
exposes:
- type: mcp
port: 3001
namespace: mock-tools
description: Mock MCP server
tools:
- name: say-hello
description: Returns a greeting
inputParameters:
- name: name
type: string
required: true
description: Name to greet
outputParameters:
- name: message
type: string
value: "Hello, {{name}}!"
This mirrors the REST mock pattern (no-adapter.yml) and is useful for prototyping, demos, and contract-first development.
⚙️ Control Port & Observability¶
Q: What is the control port?¶
A: The control port is a built-in management plane (type: "control" in capability.exposes). It provides engine-provided endpoints for health checks, Prometheus metrics, distributed traces, runtime status, configuration reload, log level control, and log streaming — without writing any code.
Q: How do I enable the control port?¶
A: Add a control adapter to your capability's exposes array:
capability:
exposes:
- type: control
port: 9090
management:
health: true
observability:
traces:
local:
buffer-size: 200
At most one control adapter is allowed per capability, and its port must not collide with any business adapter port.
Q: What endpoints does the control port provide?¶
A:
| Endpoint | Default | Description |
|---|---|---|
/health/live, /health/ready |
Enabled | Liveness and readiness probes |
/metrics |
Enabled | Prometheus scrape endpoint (requires observability) |
/traces |
Enabled | Recent trace summaries (requires observability) |
/status, /config |
Disabled | Runtime status and loaded configuration |
POST /config/reload |
Disabled | Hot-reload the capability |
POST /config/validate |
Disabled | Dry-run validation |
/logs |
Disabled | Log level control |
/logs/stream |
Disabled | SSE log streaming |
Q: How do I enable OpenTelemetry observability?¶
A: Add an observability block on the control adapter. Observability is enabled by default — you only need to set the fields you want to customize:
capability:
exposes:
- type: control
port: 9090
observability:
traces:
sampling: 1.0
propagation: w3c
exporters:
otlp:
endpoint: "{{otel_endpoint}}"
This enables distributed tracing and RED metrics (Rate, Errors, Duration) for all capability operations. Metrics are exposed in Prometheus format on the control port's /metrics endpoint.
Q: What metrics does Ikanos expose?¶
A: The engine emits three histogram metrics following the RED method:
ikanos.request.duration.seconds— end-to-end request duration by tool/operation name and statusikanos.step.duration.seconds— individual orchestration step durationikanos.http.client.duration.seconds— outbound HTTP call duration by namespace, method, and status code
A counter ikanos.request.errors tracks failed requests. All metrics are available in Prometheus text format on the control port's /metrics endpoint.
Q: How do I connect Prometheus and Grafana?¶
A: Point Prometheus at the control port's /metrics endpoint:
# prometheus.yml
scrape_configs:
- job_name: ikanos
metrics_path: /metrics
static_configs:
- targets: ['localhost:9090']
A sample Grafana dashboard is provided in demo/shared/observability/grafana-ikanos.json.
🔭 Troubleshooting & Debugging¶
Q: My capability won't start. How do I debug it?¶
A:
-
Validate your YAML first:
-
Check the Docker logs:
bash docker run ... ghcr.io/naftiko/ikanos:{{RELEASE_TAG}} serve /app/capability.yaml # Look for error messages in the output
Or, when running locally:
- Verify your file path - if using Docker, ensure:
- The volume mount is correct:
-v /absolute/path:/app/capability.yaml - The file exists and is readable
-
For Docker on Windows/Mac, use proper path translation
-
Check external services - ensure:
- APIs you're consuming are reachable
- Network connectivity is available
- Authentication credentials are correct
Q: Requests to my exposed endpoint return errors. How do I debug?¶
A:
- Check the request format - ensure headers, parameters, and body match your definition
- Verify consumed API availability - test the underlying API directly
- Inspect JsonPath mappings - ensure your extraction paths match the API response
- Use Docker logs - see server-side error messages
Q: JsonPath expressions aren't extracting the data I expect. How do I fix it?¶
A:
- Test your JsonPath - use an online tool like jsonpath.com
- Inspect the actual response - add an operation without filtering to see raw data
- Understand array syntax:
$.users[0]- first element$.users[*]- all elements (creates array output)-
$.users[*].name- all names -
For nested objects, trace the path step-by-step:
$.data.user.profile.email
Q: My parameters aren't being passed to the consumed API. What's wrong?¶
A:
- Check parameter names match - consumed parameter names must match keys in
with - Verify parameter location (
in: path,in: query,in: header, etc.) - Check variable references - ensure
{{VARIABLE_NAME}}variables are defined in binds - Test without transformation - use
forwardto proxy the request and see if underlying API works
Q: Authentication is failing. How do I debug it?¶
A:
- Test credentials directly - verify your token/key works with the API
- Check token format - ensure it's a valid token (not expired, wrong format, etc.)
- Verify placement - is the token in the right header/query/body?
- Environment variables - ensure the Docker environment variable matches the key name in
binds - Quotes - make sure tokens with special characters are properly quoted in YAML
🚣 Contributing¶
Q: How do I contribute to Ikanos?¶
A: We welcome all contributions! Here's how:
- Report bugs or request features - GitHub Issues
-
Search for existing issues first to avoid duplicates
-
Submit code changes - GitHub Pull Requests
- Create a local branch
- Ensure your code passes all build validation
-
Rebase on
mainbefore submitting -
Contribute examples - Add capability examples to the repository
- Document your use case in the example
-
Include comments explaining key features
-
Improve documentation - Fix typos, clarify docs, add examples
Q: What's the code structure and how do I set up a development environment?¶
A: Ikanos is a Java project using Maven. To build and develop:
# Clone the repository
git clone https://github.com/naftiko/ikanos.git
cd ikanos
# Build the project
mvn clean install
# Run tests
mvn test
# Build Docker image
docker build -t ikanos:local .
Key directories:
- ikanos-engine/src/main/java/io/ikanos/ Core engine code
- ikanos-spec/src/main/resources/schemas/ JSON Schema definitions
- ikanos-engine/src/test/ and ikanos-cli/src/test/ Unit and integration tests
- ikanos-spec/src/main/resources/schemas/examples/ Capability examples
- ikanos-docs/tutorial/ Tutorial capability files
Q: What are the design guidelines for creating capabilities?¶
A:
- Keep the Ikanos Specification as a first-class citizen - refer to it often
- Don't expose unused input parameters - every parameter should be used in steps
- Don't declare consumed outputs you don't use - be precise in mappings
- Don't prefix variables unnecessarily - let scope provide clarity
Example:
# Good: expose only used input
inputParameters:
- name: database_id # Used in step below
in: path
# Bad: expose unused input
inputParameters:
- name: database_id
- name: unused_param # Never used anywhere
# Good: output only consumed outputs you map
outputParameters:
- name: result
value: $.step1.output # Clearly mapped
# Bad: declare outputs you don't use
outputParameters:
- name: unused_result
value: $.step1.unused
Q: How do I test my capability changes?¶
A:
- Unit tests - Add tests in
src/test/java - Integration tests - Test against real or mock APIs
- Validation - Use the CLI tool:
ikanos validate capability.yaml - Docker testing - Build and run the Docker image with your capability
Q: Which version of Java is required?¶
A: Ikanos requires Java 21 or later. This is specified in the Maven configuration.
⛴️ Advanced Topics¶
Q: Can I use templates/variables in my capability definition?¶
A: Yes, use Mustache-style {{variable}} expressions:
binds:
- namespace: env
keys:
API_KEY: API_KEY
API_BASE_URL: API_BASE_URL
consumes:
- baseUri: "{{API_BASE_URL}}"
authentication:
type: apikey
key: X-API-Key
value: "{{API_KEY}}"
Variables come from binds and are injected at runtime.
Q: Can I compose capabilities (capability calling another capability)?¶
A: Indirectly - by referencing the exposed URL/port as a consumed API:
# Capability B "consumes" the exposed endpoint from Capability A
consumes:
- baseUri: http://localhost:8081 # Capability A's port
namespace: capability-a
This way, Capability B can combine Capability A with other APIs.
Q: How do I handle errors or retries?¶
A: Ikanos currently doesn't have built-in retry logic in v1.0.0-alpha3. Options:
- At the HTTP client level - use an API gateway with retry policies
- In future versions - this is on the roadmap
Check the Roadmap for planned features.
Q: Can I expose the same capability on both REST and MCP?¶
A: Yes! Add multiple entries to exposes:
exposes:
- type: rest
port: 8081
namespace: rest-api
resources: [...]
- type: mcp
port: 9091
namespace: mcp-server
tools: [...]
consumes: [...] # Shared between both
Both adapters consume the same sources but expose different interfaces.
💨 Performance & Deployment¶
Q: How scalable is Ikanos for high-load scenarios?¶
A: Ikanos is suitable for moderate to high loads depending on: - Your consumed APIs' performance - Ikanos's overhead is minimal - Docker/Kubernetes scaling - deploy multiple instances behind a load balancer - Orchestration complexity - simpler capabilities (forward, single calls) are faster
For production workloads: - Use Kubernetes for auto-scaling - Monitor consuming/consumed API latencies - Consider caching strategies above Ikanos
Q: How do I deploy Ikanos to production?¶
A:
-
Kubernetes (recommended):
apiVersion: apps/v1 kind: Deployment metadata: name: ikanos-engine spec: replicas: 3 template: spec: containers: - name: ikanos image: ghcr.io/naftiko/ikanos:{{RELEASE_TAG}} volumeMounts: - name: capability mountPath: /app/capability.yaml subPath: capability.yaml env: - name: GITHUB_TOKEN valueFrom: secretKeyRef: name: ikanos-secrets key: github-token -
Docker Compose - for simpler setups
- Environment Variables - inject secrets via
binds(omitlocationfor runtime injection)
Q: Can I use Ikanos behind a reverse proxy (nginx, Envoy)?¶
A: Yes, absolutely. Ikanos exposes standard HTTP endpoints, so it works with any reverse proxy.
Example (nginx):
📜 Specifications & Standards¶
Q: How does Ikanos compare to OpenAPI, AsyncAPI, or Arazzo?¶
A: Ikanos is complementary to these specifications and combines their strengths into a single runtime model: - Consume/expose duality - like OpenAPI's interface description, but bidirectional - Orchestration - like Arazzo's workflow sequencing - AI-driven discovery - beyond what all three cover natively - Namespace-based routing - unique to Ikanos's runtime approach
See the Spec-Driven Integration overview and the Specification - Schema for the formal model.
Q: Is the Ikanos Specification stable?¶
A: The current public version is {{RELEASE_TAG}}. Because this is an alpha release, minor schema adjustments can still happen before stable 1.0.0. The specification follows semantic versioning: - Major versions (1.x.x) - breaking changes - Minor versions (x.1.0) - new features, backward-compatible - Patch versions (x.x.1) - bug fixes
Check the Ikanos field in your YAML to specify the version.
📣 Community & Support¶
Q: Where can I ask questions or discuss ideas?¶
A: Join the community at: - GitHub Discussions - Ask questions and share ideas - GitHub Issues - Report bugs or request features - Pull Requests - Review and discuss code changes
Q: Are there examples I can reference?¶
A: Yes! Several resources:
- Tutorial — Track 1: Context Engineering - Mock-first MCP, wiring to a real API, auth, output shaping (Steps 1–7)
- Tutorial — Track 2: API Reusability - Skill groups, aggregates with
ref, and a parallel REST adapter (Steps 8–10) - Tutorial — Track 3: Agent Orchestration - The Fleet Manifest capstone (Step 11) — multi-source orchestrated
stepsandlookupjoins - Use Cases - Real-world examples
- Repository examples - In
ikanos-spec/src/main/resources/schemas/examples/,ikanos-docs/tutorial/, and test resources - Specification examples - In the Specification - Schema (Section 4)
Q: How often is Ikanos updated?¶
A: Check the Releases page for version history. The project follows a regular release cadence with security updates prioritized.
🚤 Common Use Cases¶
Q: I want to create a unified REST API that combines Notion + GitHub. How do I start?¶
A:
- Read the Tutorial - particularly steps 1-6 for foundations and steps 7-10 for advanced needs
- Define consumed sources - GitHub and Notion APIs with auth
- Design exposed resources - endpoints that combine their data
- Use multi-step orchestration - call both APIs and map results
- Test locally - use Docker to run your capability
Q: I want to expose my capability as an MCP tool for Claude. How do I do this?¶
A:
- Use
type: mcpinexposes - Define
tools- each tool is an MCP tool your capability provides - Add
hints(optional) - declare behavioral hints likereadOnly,destructive,idempotent,openWorldto help clients understand tool safety - Use stdio transport - for native Claude Desktop integration
- Test with Claude - configure Claude Desktop with your MCP server
- Publish - share your capability spec with the community
See Tutorial — Track 1: Context Engineering for a full MCP example, then continue with Tutorial — Track 2: API Reusability for Skill and REST exposure.
Q: I want to standardize data from multiple SaaS tools. How do I use Ikanos?¶
A:
- Consume multiple SaaS APIs - define each in
consumes - Normalize outputs - use
outputParametersto extract and structure data consistently - Expose unified interface - create a single API with harmonized formats
- Use orchestration - combine data from multiple sources if needed
This is Ikanos's core strength for managing API sprawl.
🏝️ Additional Resources¶
- Installation - Setup instructions
- Spec-Driven Integration - Methodology overview
- Tutorial — Track 1: Context Engineering - Mock-first MCP and contract-first foundations (Steps 1–7)
- Tutorial — Track 2: API Reusability - Skill groups, aggregates, REST adapter (Steps 8–10)
- Tutorial — Track 3: Agent Orchestration - Fleet Manifest orchestration (Step 11)
- Guide - Use Cases - Real-world examples
- Guide - Linting - Validation workflow and CLI usage
- Specification - Schema - Complete technical reference
- Specification - Rules - Validation and linting rules
- Releases - Version history
- Roadmap - Future plans
- Contribute - Become a contributor
- Discussions - Community Q&A
🔔 Feedback¶
Did this FAQ help you? Have questions not covered here? - Add an issue - GitHub Issues - Start a discussion - GitHub Discussions - Submit a PR - Help us improve this FAQ!