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.

varianteai_variant_tEAI variant: Min, Framework.
modeeai_mode_tExecution mode (online/offline/hybrid).
runtime_singleeai_runtime_config_single_tEAI-Min: single provider name string.
runtime_multieai_runtime_config_multi_tEAI-Framework: up to 8 providers.
tools[32]const char *Enabled tool names (max 32).
tool_countintNumber of enabled tools.
connectors[16]const char *Connector names (Framework only, max 16).
connector_countintNumber of connectors.
policy.cloud_fallbackboolAllow cloud API fallback when local inference fails.
observabilityboolEnable tracing and metrics collection.

eai_status_t (Return Codes)

EAI_OK0Success.
EAI_ERR-1Generic error.
EAI_ERR_OOM-2Out of memory.
EAI_ERR_NOT_FOUND-3Tool/model/key not found.
EAI_ERR_FULL-4Registry or memory full.
EAI_ERR_INVALID-5Invalid 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
cfgeai_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
cfgeai_config_t *Config struct to populate (should be pre-initialized).
pathconst 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 config
eai_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
cfgeai_config_t *Config struct to populate.
profile_nameconst 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
cfgconst 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
cfgeai_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]charTool name (e.g., "gpio_control", "sensor_read").
descriptionconst char *Human-readable description for the LLM.
params[16]eai_tool_param_tParameter definitions (name, type, required).
param_countintNumber of parameters.
permissions[8]const char *Required permissions (e.g., "hw.gpio", "net.send").
permission_countintNumber of permissions.
execeai_tool_exec_fnExecution callback function pointer.

eai_param_type_t

EAI_PARAM_STRING0String parameter.
EAI_PARAM_INT1Integer parameter.
EAI_PARAM_FLOAT2Float parameter.
EAI_PARAM_BOOL3Boolean parameter.
EAI_PARAM_BYTES4Binary data parameter.

eai_tool_result_t

data[4096]charResult data buffer (JSON or text).
lensize_tLength of result data.
statuseai_status_tExecution 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
regeai_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
regeai_tool_registry_t *Target registry.
toolconst 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(&reg);
eai_tool_register(&reg, &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
regeai_tool_registry_t *Registry to search.
nameconst 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
tooleai_tool_t *Tool to execute.
argsconst eai_kv_t *Array of key-value argument pairs.
arg_countintNumber of arguments.
resulteai_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
regconst 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

runtimeeai_min_runtime_t *Pointer to LLM runtime (llama.cpp, ONNX, TFLite).
toolseai_tool_registry_t *Pointer to tool registry.
memoryeai_mem_lite_t *Pointer to key-value memory store.
stateeai_agent_state_tCurrent state: IDLE, THINKING, TOOL_CALL, DONE, ERROR.
iterationintCurrent iteration count.
last_output[4096]charLast output from the agent.

eai_agent_state_t

EAI_AGENT_IDLE0Agent initialized, not running.
EAI_AGENT_THINKING1LLM is generating a response.
EAI_AGENT_TOOL_CALL2Agent is executing a tool call.
EAI_AGENT_DONE3Task completed successfully.
EAI_AGENT_ERROR4Error occurred.

eai_agent_task_t

goalconst char *Task description / user prompt.
offline_onlyboolRestrict to offline tools only.
max_iterationsintMax 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
agenteai_min_agent_t *Agent to initialize.
runtimeeai_min_runtime_t *Initialized LLM runtime.
toolseai_tool_registry_t *Initialized tool registry with registered tools.
memoryeai_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
agenteai_min_agent_t *Initialized agent.
taskconst 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
agenteai_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
agentconst 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
agenteai_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_tMemory entries (max EAI_MEM_MAX_ENTRIES=128).
countintCurrent number of entries.
storage_pathconst char *File path for persistent entries (NULL for RAM-only).

eai_mem_entry_t

key[64]charEntry key (max 63 chars).
value[512]charEntry value (max 511 chars).
timestampuint64_tCreation/update timestamp.
persistentboolWhether 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
memeai_mem_lite_t *Memory store to initialize.
storage_pathconst 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 flash
eai_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
memeai_mem_lite_t *Memory store.
keyconst char *Key (max 63 chars).
valueconst char *Value (max 511 chars).
persistentboolSave 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
memconst eai_mem_lite_t *Memory store.
keyconst 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

nameconst char *Model name (e.g., "TinyLlama-1.1B-Q4_0").
familyconst char *Model family (e.g., "LLaMA", "Phi", "Qwen").
descriptionconst char *Short description.
quanteai_quant_tQuantization: F32, F16, Q8_0, Q5_1, Q5_0, Q4_1, Q4_0, Q3_K, Q2_K, IQ2.
runtimeeai_runtime_tRuntime: LLAMA_CPP(0), ONNX(1), TFLITE(2), CUSTOM(3).
tiereai_model_tier_tMICRO(<100MB), TINY(100-500MB), SMALL(500MB-2GB), MEDIUM(2-4GB), LARGE(4GB+).
param_count_muint32_tParameters in millions.
context_lenuint32_tMax context tokens.
ram_mbuint32_tRAM required in MB.
storage_mbuint32_tStorage required in MB.
tokens_per_secuint32_tApprox tokens/sec on target hardware.
target_hardwareconst char *Recommended hardware.
licenseconst char *License type.
gguf_fileconst char *GGUF filename for llama.cpp.

eai_quant_t

EAI_QUANT_F320Full 32-bit float (largest, highest quality).
EAI_QUANT_F161Half-precision float.
EAI_QUANT_Q8_028-bit quantization.
EAI_QUANT_Q5_135-bit with 1-bit scale.
EAI_QUANT_Q5_045-bit quantization.
EAI_QUANT_Q4_154-bit with 1-bit scale.
EAI_QUANT_Q4_064-bit quantization (recommended for embedded).
EAI_QUANT_Q3_K73-bit K-quant.
EAI_QUANT_Q2_K82-bit K-quant (smallest, lowest quality).
EAI_QUANT_IQ29Importance-weighted 2-bit.

eai_model_tier_t

EAI_MODEL_TIER_MICRO0<100MB. MCU-class: Cortex-M7, RP2040.
EAI_MODEL_TIER_TINY1100-500MB. Low-end SBC: RPi3, nRF5340.
EAI_MODEL_TIER_SMALL2500MB-2GB. Mid SBC: RPi4, i.MX8M.
EAI_MODEL_TIER_MEDIUM32-4GB. High SBC: Jetson Nano, RPi5.
EAI_MODEL_TIER_LARGE44GB+. 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
nameconst 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
tiereai_model_tier_tTarget 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_mbuint32_tAvailable RAM in MB.
storage_mbuint32_tAvailable 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

ModelFamilyParamsQuantRAMStoragetok/sTierHardware
SmolLM-135M-Q4_0SmolLM135MQ4_080MB70MB~12MICROCortex-M7, RP2040
TinyStories-33M-Q8TinyStories33MQ8_045MB35MB~25MICROCortex-M7
Phi-2-Q4_0Phi2700MQ4_01800MB1500MB~8SMALLRPi4, i.MX8M
TinyLlama-1.1B-Q4_0LLaMA1100MQ4_0700MB600MB~10SMALLRPi4
Qwen2-0.5B-Q4_0Qwen500MQ4_0350MB300MB~15TINYnRF5340, RPi3
Gemma-2B-Q4_0Gemma2000MQ4_01500MB1200MB~6SMALLRPi4
LLaMA-3.2-3B-Q4_0LLaMA3000MQ4_02500MB2000MB~5MEDIUMJetson Nano, RPi5
Mistral-7B-Q2_KMistral7000MQ2_K4000MB3000MB~3LARGEJetson 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 changes

Thread 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.