EAI Developer Documentation v0.1.0
Embedded AI framework for on-device LLM inference, tool-calling agents, model management, and runtime configuration. Headers: <eai/config.h>, <eai/tool.h>, <eai_min/agent.h>, <eai_min/memory_lite.h>, <eai/models.h>
⚙ Configuration API
Runtime configuration for EAI variants. Header: <eai/config.h>
eai_config_t
Master configuration for EAI runtime.
variant | eai_variant_t | EAI variant: Min, Framework. |
mode | eai_mode_t | Execution mode (online/offline/hybrid). |
runtime_single | eai_runtime_config_single_t | EAI-Min: single provider name string. |
runtime_multi | eai_runtime_config_multi_t | EAI-Framework: up to 8 providers. |
tools[32] | const char * | Enabled tool names (max 32). |
tool_count | int | Number of enabled tools. |
connectors[16] | const char * | Connector names (Framework only, max 16). |
connector_count | int | Number of connectors. |
policy.cloud_fallback | bool | Allow cloud API fallback when local inference fails. |
observability | bool | Enable tracing and metrics collection. |
eai_status_t (Return Codes)
EAI_OK | 0 | Success. |
EAI_ERR | -1 | Generic error. |
EAI_ERR_OOM | -2 | Out of memory. |
EAI_ERR_NOT_FOUND | -3 | Tool/model/key not found. |
EAI_ERR_FULL | -4 | Registry or memory full. |
EAI_ERR_INVALID | -5 | Invalid parameter. |
eai_status_t eai_config_init(eai_config_t *cfg)Initialize configuration with safe defaults: variant=Min, mode=offline, no tools, no connectors, cloud_fallback=false, observability=false.
Parameters
cfg | eai_config_t * | Config struct to initialize. All fields zeroed and set to defaults. |
Returns
EAI_OK on success. EAI_ERR_INVALID if cfg is NULL.
Example
eai_config_t cfg;
eai_config_init(&cfg);
cfg.variant = EAI_VARIANT_MIN;
cfg.runtime_single.provider = "llama_cpp";
cfg.tools[0] = "gpio_control";
cfg.tools[1] = "sensor_read";
cfg.tool_count = 2;eai_status_t eai_config_load_file(eai_config_t *cfg, const char *path)Load configuration from a YAML or JSON file. Supports all eai_config_t fields. File format auto-detected by extension (.yml/.yaml/.json).
Parameters
cfg | eai_config_t * | Config struct to populate (should be pre-initialized). |
path | const char * | Path to config file (absolute or relative to CWD). |
Returns
EAI_OK on success. EAI_ERR_NOT_FOUND if file missing. EAI_ERR on parse error.
Example
eai_config_t cfg;
eai_config_init(&cfg);
if (eai_config_load_file(&cfg, "/etc/eai/config.yml") != EAI_OK) {
EOS_WARN("Config load failed, using defaults");
}
eai_config_dump(&cfg); // Print loaded configeai_status_t eai_config_load_profile(eai_config_t *cfg, const char *profile_name)Load a named profile such as "production", "debug", or "minimal". Profiles are pre-defined configurations optimized for specific use cases.
Parameters
cfg | eai_config_t * | Config struct to populate. |
profile_name | const char * | Profile name: "production", "debug", "minimal", "benchmark". |
Returns
EAI_OK on success. EAI_ERR_NOT_FOUND if profile unknown.
void eai_config_dump(const eai_config_t *cfg)Print all configuration fields to stdout for debugging. Shows variant, mode, provider, tools, connectors, and policy settings.
Parameters
cfg | const eai_config_t * | Config to dump. Not modified. |
void eai_config_free(eai_config_t *cfg)Free any heap-allocated resources within the config struct (e.g., strings loaded from file).
Parameters
cfg | eai_config_t * | Config to free. Safe to call on stack-allocated configs. |
🔧 Tool Registry API
Register callable tools for AI agents. Header: <eai/tool.h>
eai_tool_t
name[64] | char | Tool name (e.g., "gpio_control", "sensor_read"). |
description | const char * | Human-readable description for the LLM. |
params[16] | eai_tool_param_t | Parameter definitions (name, type, required). |
param_count | int | Number of parameters. |
permissions[8] | const char * | Required permissions (e.g., "hw.gpio", "net.send"). |
permission_count | int | Number of permissions. |
exec | eai_tool_exec_fn | Execution callback function pointer. |
eai_param_type_t
EAI_PARAM_STRING | 0 | String parameter. |
EAI_PARAM_INT | 1 | Integer parameter. |
EAI_PARAM_FLOAT | 2 | Float parameter. |
EAI_PARAM_BOOL | 3 | Boolean parameter. |
EAI_PARAM_BYTES | 4 | Binary data parameter. |
eai_tool_result_t
data[4096] | char | Result data buffer (JSON or text). |
len | size_t | Length of result data. |
status | eai_status_t | Execution status. |
eai_status_t eai_tool_registry_init(eai_tool_registry_t *reg)Initialize a tool registry. Zeroes all slots and sets count to 0. Maximum EAI_TOOL_REGISTRY_MAX (64) tools.
Parameters
reg | eai_tool_registry_t * | Registry to initialize. |
Returns
EAI_OK on success.
eai_status_t eai_tool_register(eai_tool_registry_t *reg, const eai_tool_t *tool)Register a tool in the registry. Copies the tool definition. The tool's exec callback will be invoked when the agent calls this tool.
Parameters
reg | eai_tool_registry_t * | Target registry. |
tool | const eai_tool_t * | Tool definition to register. |
Returns
EAI_OK on success. EAI_ERR_FULL if registry has 64 tools.
Example
eai_status_t gpio_exec(const eai_kv_t *args, int n, eai_tool_result_t *r) {
int pin = atoi(eai_kv_get(args, n, "pin"));
bool val = strcmp(eai_kv_get(args, n, "value"), "true") == 0;
eos_gpio_write(pin, val);
snprintf(r->data, sizeof(r->data), "{\"ok\":true,\"pin\":%d}", pin);
r->len = strlen(r->data);
r->status = EAI_OK;
return EAI_OK;
}
eai_tool_t gpio_tool = {
.name = "gpio_write",
.description = "Set a GPIO pin HIGH or LOW",
.params = {
{ .name = "pin", .type = EAI_PARAM_INT, .required = true },
{ .name = "value", .type = EAI_PARAM_BOOL, .required = true }
},
.param_count = 2,
.permissions = { "hw.gpio" },
.permission_count = 1,
.exec = gpio_exec
};
eai_tool_registry_t reg;
eai_tool_registry_init(®);
eai_tool_register(®, &gpio_tool);eai_tool_t * eai_tool_find(eai_tool_registry_t *reg, const char *name)Find a tool by name. Returns pointer to the registered tool or NULL if not found.
Parameters
reg | eai_tool_registry_t * | Registry to search. |
name | const char * | Tool name to find. |
Returns
Pointer to eai_tool_t, or NULL if not found.
eai_status_t eai_tool_exec(eai_tool_t *tool, const eai_kv_t *args, int arg_count, eai_tool_result_t *result)Execute a tool with the given arguments. Calls the tool's exec callback. The result buffer is populated with the tool's output (typically JSON).
Parameters
tool | eai_tool_t * | Tool to execute. |
args | const eai_kv_t * | Array of key-value argument pairs. |
arg_count | int | Number of arguments. |
result | eai_tool_result_t * | Output buffer for result (4096 bytes max). |
Returns
EAI_OK on success. Tool-specific error codes possible.
void eai_tool_registry_list(const eai_tool_registry_t *reg)Print all registered tools with their names, descriptions, and parameter lists to stdout.
Parameters
reg | const eai_tool_registry_t * | Registry to list. |
🤖 Agent API (EAI-Min)
Lightweight ReAct agent loop for embedded devices. Header: <eai_min/agent.h>
eai_min_agent_t
runtime | eai_min_runtime_t * | Pointer to LLM runtime (llama.cpp, ONNX, TFLite). |
tools | eai_tool_registry_t * | Pointer to tool registry. |
memory | eai_mem_lite_t * | Pointer to key-value memory store. |
state | eai_agent_state_t | Current state: IDLE, THINKING, TOOL_CALL, DONE, ERROR. |
iteration | int | Current iteration count. |
last_output[4096] | char | Last output from the agent. |
eai_agent_state_t
EAI_AGENT_IDLE | 0 | Agent initialized, not running. |
EAI_AGENT_THINKING | 1 | LLM is generating a response. |
EAI_AGENT_TOOL_CALL | 2 | Agent is executing a tool call. |
EAI_AGENT_DONE | 3 | Task completed successfully. |
EAI_AGENT_ERROR | 4 | Error occurred. |
eai_agent_task_t
goal | const char * | Task description / user prompt. |
offline_only | bool | Restrict to offline tools only. |
max_iterations | int | Max ReAct iterations (default: EAI_AGENT_MAX_ITERATIONS=10). |
eai_status_t eai_min_agent_init(eai_min_agent_t *agent, eai_min_runtime_t *runtime, eai_tool_registry_t *tools, eai_mem_lite_t *memory)Initialize an EAI-Min agent with a runtime, tool registry, and memory store. Sets state to IDLE. All three subsystems must be initialized before calling this.
Parameters
agent | eai_min_agent_t * | Agent to initialize. |
runtime | eai_min_runtime_t * | Initialized LLM runtime. |
tools | eai_tool_registry_t * | Initialized tool registry with registered tools. |
memory | eai_mem_lite_t * | Initialized memory store (can be NULL for stateless mode). |
Returns
EAI_OK on success. EAI_ERR_INVALID if agent or runtime is NULL.
eai_status_t eai_min_agent_run(eai_min_agent_t *agent, const eai_agent_task_t *task)Run the agent's ReAct loop to completion. Iterates: Think → Tool Call → Observe → Think until the agent signals DONE or reaches max_iterations. This is a blocking call that may take seconds to minutes depending on model size and task complexity.
Parameters
agent | eai_min_agent_t * | Initialized agent. |
task | const eai_agent_task_t * | Task description with goal and constraints. |
Returns
EAI_OK if task completed. EAI_ERR on LLM inference failure. EAI_ERR_OOM on memory exhaustion.
Example
eai_agent_task_t task = {
.goal = "Read the temperature sensor and turn on the fan if above 35C",
.offline_only = true,
.max_iterations = 5
};
eai_status_t rc = eai_min_agent_run(&agent, &task);
if (rc == EAI_OK) {
printf("Agent result: %s\n", eai_min_agent_output(&agent));
} else {
printf("Agent failed after %d iterations\n", agent.iteration);
}eai_status_t eai_min_agent_step(eai_min_agent_t *agent)Execute a single ReAct iteration. Use instead of eai_min_agent_run() when you need fine-grained control, logging between steps, or need to run the agent cooperatively within an RTOS task.
Parameters
agent | eai_min_agent_t * | Agent (must have had run() called to set the task, or be in THINKING/TOOL_CALL state). |
Returns
EAI_OK if step completed. Check agent->state for DONE/ERROR.
const char * eai_min_agent_output(const eai_min_agent_t *agent)Get the agent's final output text after a completed run.
Parameters
agent | const eai_min_agent_t * | Agent (should be in DONE state). |
Returns
Pointer to output string (up to 4096 chars), or empty string if agent hasn't completed.
void eai_min_agent_reset(eai_min_agent_t *agent)Reset agent to IDLE state. Clears iteration count and last output. Does not affect runtime, tools, or memory.
Parameters
agent | eai_min_agent_t * | Agent to reset. |
💾 Memory Lite API
Key-value memory store for agent state persistence. Header: <eai_min/memory_lite.h>
eai_mem_lite_t
entries[128] | eai_mem_entry_t | Memory entries (max EAI_MEM_MAX_ENTRIES=128). |
count | int | Current number of entries. |
storage_path | const char * | File path for persistent entries (NULL for RAM-only). |
eai_mem_entry_t
key[64] | char | Entry key (max 63 chars). |
value[512] | char | Entry value (max 511 chars). |
timestamp | uint64_t | Creation/update timestamp. |
persistent | bool | Whether entry survives reboot (saved to flash/disk). |
eai_status_t eai_mem_lite_init(eai_mem_lite_t *mem, const char *storage_path)Initialize memory store. If storage_path is non-NULL, persistent entries will be saved/loaded from that file.
Parameters
mem | eai_mem_lite_t * | Memory store to initialize. |
storage_path | const char * | Path for persistent storage (NULL for RAM-only). |
Returns
EAI_OK on success.
Example
eai_mem_lite_t mem;
eai_mem_lite_init(&mem, "/data/eai_memory.bin");
eai_mem_lite_load(&mem); // Load persistent entries from previous run
eai_mem_lite_set(&mem, "user_preference", "metric_units", true);
eai_mem_lite_set(&mem, "last_temp_reading", "23.5", false);
const char *pref = eai_mem_lite_get(&mem, "user_preference");
printf("User prefers: %s\n", pref);
eai_mem_lite_save(&mem); // Persist to flasheai_status_t eai_mem_lite_set(eai_mem_lite_t *mem, const char *key, const char *value, bool persistent)Set or update a key-value pair. If key exists, overwrites value and persistent flag.
Parameters
mem | eai_mem_lite_t * | Memory store. |
key | const char * | Key (max 63 chars). |
value | const char * | Value (max 511 chars). |
persistent | bool | Save to flash on eai_mem_lite_save(). |
Returns
EAI_OK on success. EAI_ERR_FULL if 128 entries reached.
const char * eai_mem_lite_get(const eai_mem_lite_t *mem, const char *key)Get value by key. Returns NULL if key not found.
Parameters
mem | const eai_mem_lite_t * | Memory store. |
key | const char * | Key to look up. |
Returns
Pointer to value string, or NULL if not found.
eai_status_t eai_mem_lite_delete(eai_mem_lite_t *mem, const char *key) / eai_mem_lite_save(const eai_mem_lite_t *mem) / eai_mem_lite_load(eai_mem_lite_t *mem) / eai_mem_lite_clear(eai_mem_lite_t *mem)delete: Remove key. save: Write persistent entries to storage_path. load: Read persistent entries from storage_path. clear: Remove all entries from memory.
int eai_mem_lite_count(const eai_mem_lite_t *mem)Get current number of entries stored.
Returns
Entry count (0-128).
🤖 Model Registry
Curated LLM model database for embedded targets. Header: <eai/models.h>
eai_model_info_t
name | const char * | Model name (e.g., "TinyLlama-1.1B-Q4_0"). |
family | const char * | Model family (e.g., "LLaMA", "Phi", "Qwen"). |
description | const char * | Short description. |
quant | eai_quant_t | Quantization: F32, F16, Q8_0, Q5_1, Q5_0, Q4_1, Q4_0, Q3_K, Q2_K, IQ2. |
runtime | eai_runtime_t | Runtime: LLAMA_CPP(0), ONNX(1), TFLITE(2), CUSTOM(3). |
tier | eai_model_tier_t | MICRO(<100MB), TINY(100-500MB), SMALL(500MB-2GB), MEDIUM(2-4GB), LARGE(4GB+). |
param_count_m | uint32_t | Parameters in millions. |
context_len | uint32_t | Max context tokens. |
ram_mb | uint32_t | RAM required in MB. |
storage_mb | uint32_t | Storage required in MB. |
tokens_per_sec | uint32_t | Approx tokens/sec on target hardware. |
target_hardware | const char * | Recommended hardware. |
license | const char * | License type. |
gguf_file | const char * | GGUF filename for llama.cpp. |
eai_quant_t
EAI_QUANT_F32 | 0 | Full 32-bit float (largest, highest quality). |
EAI_QUANT_F16 | 1 | Half-precision float. |
EAI_QUANT_Q8_0 | 2 | 8-bit quantization. |
EAI_QUANT_Q5_1 | 3 | 5-bit with 1-bit scale. |
EAI_QUANT_Q5_0 | 4 | 5-bit quantization. |
EAI_QUANT_Q4_1 | 5 | 4-bit with 1-bit scale. |
EAI_QUANT_Q4_0 | 6 | 4-bit quantization (recommended for embedded). |
EAI_QUANT_Q3_K | 7 | 3-bit K-quant. |
EAI_QUANT_Q2_K | 8 | 2-bit K-quant (smallest, lowest quality). |
EAI_QUANT_IQ2 | 9 | Importance-weighted 2-bit. |
eai_model_tier_t
EAI_MODEL_TIER_MICRO | 0 | <100MB. MCU-class: Cortex-M7, RP2040. |
EAI_MODEL_TIER_TINY | 1 | 100-500MB. Low-end SBC: RPi3, nRF5340. |
EAI_MODEL_TIER_SMALL | 2 | 500MB-2GB. Mid SBC: RPi4, i.MX8M. |
EAI_MODEL_TIER_MEDIUM | 3 | 2-4GB. High SBC: Jetson Nano, RPi5. |
EAI_MODEL_TIER_LARGE | 4 | 4GB+. Edge server: x86, Jetson Orin. |
const eai_model_info_t * eai_model_find(const char *name)Find a model by exact name. Returns NULL if not found.
Parameters
name | const char * | Model name. |
Returns
Pointer to model info, or NULL.
const eai_model_info_t * eai_model_find_by_tier(eai_model_tier_t tier)Find the first model matching a tier. Use to get the recommended model for your hardware class.
Parameters
tier | eai_model_tier_t | Target tier: MICRO, TINY, SMALL, MEDIUM, LARGE. |
Returns
Pointer to model info, or NULL.
const eai_model_info_t * eai_model_find_best_fit(uint32_t ram_mb, uint32_t storage_mb)Find the largest model that fits within the given RAM and storage constraints. Returns the best quality model your hardware can run.
Parameters
ram_mb | uint32_t | Available RAM in MB. |
storage_mb | uint32_t | Available storage in MB. |
Returns
Pointer to best-fit model info, or NULL if nothing fits.
Example
// Auto-select best model for available resources
const eai_model_info_t *model = eai_model_find_best_fit(512, 1024);
if (model) {
printf("Selected: %s (%s, %uM params, %u MB RAM)\n",
model->name, model->family,
model->param_count_m, model->ram_mb);
printf("GGUF file: %s\n", model->gguf_file);
printf("Expected: ~%u tokens/sec\n", model->tokens_per_sec);
} else {
printf("No model fits in 512MB RAM / 1GB storage\n");
}void eai_model_list(void)Print all registered models to stdout with their names, tiers, sizes, and hardware targets.
📊 LLM Model Table
| Model | Family | Params | Quant | RAM | Storage | tok/s | Tier | Hardware |
| SmolLM-135M-Q4_0 | SmolLM | 135M | Q4_0 | 80MB | 70MB | ~12 | MICRO | Cortex-M7, RP2040 |
| TinyStories-33M-Q8 | TinyStories | 33M | Q8_0 | 45MB | 35MB | ~25 | MICRO | Cortex-M7 |
| Phi-2-Q4_0 | Phi | 2700M | Q4_0 | 1800MB | 1500MB | ~8 | SMALL | RPi4, i.MX8M |
| TinyLlama-1.1B-Q4_0 | LLaMA | 1100M | Q4_0 | 700MB | 600MB | ~10 | SMALL | RPi4 |
| Qwen2-0.5B-Q4_0 | Qwen | 500M | Q4_0 | 350MB | 300MB | ~15 | TINY | nRF5340, RPi3 |
| Gemma-2B-Q4_0 | Gemma | 2000M | Q4_0 | 1500MB | 1200MB | ~6 | SMALL | RPi4 |
| LLaMA-3.2-3B-Q4_0 | LLaMA | 3000M | Q4_0 | 2500MB | 2000MB | ~5 | MEDIUM | Jetson Nano, RPi5 |
| Mistral-7B-Q2_K | Mistral | 7000M | Q2_K | 4000MB | 3000MB | ~3 | LARGE | Jetson Orin, x86 |
🔄 Agent Loop Walkthrough
// Complete EAI-Min agent setup and execution
#include <eai/config.h>
#include <eai/tool.h>
#include <eai_min/agent.h>
#include <eai_min/memory_lite.h>
#include <eai/models.h>
// 1. Select model based on hardware
const eai_model_info_t *model = eai_model_find_best_fit(512, 1024);
// 2. Initialize LLM runtime
eai_min_runtime_t runtime;
eai_min_runtime_init(&runtime, model->gguf_file, model->context_len);
// 3. Register tools
eai_tool_registry_t tools;
eai_tool_registry_init(&tools);
eai_tool_register(&tools, &gpio_tool);
eai_tool_register(&tools, &sensor_tool);
eai_tool_register(&tools, &motor_tool);
// 4. Initialize memory
eai_mem_lite_t mem;
eai_mem_lite_init(&mem, "/data/agent_memory.bin");
eai_mem_lite_load(&mem);
// 5. Create and run agent
eai_min_agent_t agent;
eai_min_agent_init(&agent, &runtime, &tools, &mem);
eai_agent_task_t task = {
.goal = "Check all temperature sensors. If any exceed 40C, "
"activate the cooling fan on GPIO pin 12.",
.offline_only = true,
.max_iterations = 5
};
eai_status_t rc = eai_min_agent_run(&agent, &task);
printf("Result: %s\n", eai_min_agent_output(&agent));
// Agent internally executes:
// Iteration 1: THINK → "I need to read temperature sensors"
// TOOL → sensor_read(sensor="temp_1") → {"temp_c": 38.2}
// Iteration 2: THINK → "Sensor 1 is 38.2C, let me check sensor 2"
// TOOL → sensor_read(sensor="temp_2") → {"temp_c": 42.7}
// Iteration 3: THINK → "Sensor 2 exceeds 40C! Activating fan."
// TOOL → gpio_write(pin=12, value=true) → {"ok": true}
// Iteration 4: DONE → "Temperature alert: Sensor 2 at 42.7C.
// Cooling fan activated on GPIO 12."
eai_mem_lite_save(&mem); // Persist any state changesThread Safety: EAI-Min agent is NOT thread-safe. Run a single agent per task. The tool registry and memory store can be shared if protected by a mutex. LLM runtime is single-threaded by design.