Skill: cognary/aionis (version 1.0.0)

--- name: aionis_memory_policy_loop description: Connect OpenClaw to Aionis using write/context/policy/feedback memory loop APIs. homepage: https://doc.aionisos.com/public/en/integrations/04-openclaw metadata: {"openclaw":{"homepage":"https://doc.aionisos.com/public/en/integrations/04-openclaw"}} --- # Aionis Memory Policy Loop Skill Use this skill when the user asks for long-term memory, retrieval with citations, tool routing from memory rules, or feedback-driven policy adaptation. ## Requirements (Local Standalone) Environment variables: 1. `AIONIS_BASE_URL`: - host run: `http://127.0.0.1:3001` - container-to-host run: `http://host.docker.internal:3001` 2. One auth method: - `AIONIS_API_KEY` - or `AIONIS_AUTH_BEARER` 3. Optional: - `AIONIS_TENANT_ID` (default: `default`) - `AIONIS_SCOPE_PREFIX` (default: `clawbot`) ## Safety Rules 1. Never print full secrets in responses. 2. Keep scope fixed per project: `clawbot:<project>`. 3. Do not write raw tool output dumps into memory; store concise summaries. 4. Keep requests bounded: set limits for recall and context assembly. 5. If `/v1/memory/context/assemble` is unavailable, fallback to `/v1/memory/recall_text` and continue. ## Connectivity Precheck Before running the memory loop, ensure Aionis standalone is reachable: 1. `GET /health` returns `200`. 2. `POST /v1/memory/write` with `x-api-key` returns `200`. 3. If check fails, stop and return a clear connectivity/auth error. ## Auto Bootstrap Command If local standalone is not running, execute: ```bash bash ./bootstrap-local-standalone.sh ``` Then load runtime env: ```bash source ./.runtime/clawbot.env ``` ## Default Workflow 1. Ingest key facts/results: - `POST /v1/memory/write` 2. Build layered context before planning: - `POST /v1/memory/context/assemble` - fallback to `POST /v1/memory/recall_text` if assemble endpoint is unavailable 3. Route tools with policy: - `POST /v1/memory/tools/select` 4. Close the loop after execution: - `POST /v1/memory/tools/feedback` ## Request Templates Use these templates (replace placeholders): ### write ```json { "tenant_id": "default", "scope": "clawbot:demo-project", "input_text": "Customer prefers email follow-up", "auto_embed": true, "nodes": [ { "client_id": "evt_001", "type": "event", "text_summary": "Customer prefers email follow-up", "memory_lane": "shared", "slots": { "integration": "openclaw", "kind": "event", "project": "demo-project" } } ], "edges": [] } ``` ### context assemble ```json { "tenant_id": "default", "scope": "clawbot:demo-project", "query_text": "How should I follow up with this customer?", "include_rules": true, "include_shadow": false, "rules_limit": 50, "tool_strict": false, "return_layered_context": true, "context_layers": { "enabled": ["facts", "episodes", "rules", "decisions", "tools", "citations"], "char_budget_total": 3200, "include_merge_trace": true }, "limit": 30, "neighborhood_hops": 2, "max_nodes": 50, "max_edges": 100 } ``` ### tools select ```json { "tenant_id": "default", "scope": "clawbot:demo-project", "run_id": "run_001", "context": { "intent": "follow_up", "customer": { "prefers": "email" } }, "candidates": ["send_email", "call_crm", "search_docs"], "include_shadow": false, "rules_limit": 50, "strict": false } ``` ### tools feedback ```json { "tenant_id": "default", "scope": "clawbot:demo-project", "run_id": "run_001", "outcome": "positive", "context": { "intent": "follow_up", "customer": { "prefers": "email" } }, "candidates": ["send_email", "call_crm", "search_docs"], "selected_tool": "send_email", "include_shadow": false, "rules_limit": 50, "target": "tool", "input_text": "openclaw feedback accepted tool send_email" } ``` ## Output Expectations When using this skill, include these IDs in your response when present: 1. `request_id` 2. `commit_id` or `commit_uri` 3. `decision_id` or `decision_uri` 4. `run_id` Also include: 5. `base_url` used for this run 6. `scope` used for this run

path: bootstrap-local-standalone.sh
content: #!/usr/bin/env bash
set -euo pipefail

SKILL_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
RUNTIME_DIR="${AIONIS_RUNTIME_DIR:-${SKILL_DIR}/.runtime}"
ENV_FILE="${RUNTIME_DIR}/aionis.env"
CLAWBOT_ENV_FILE="${RUNTIME_DIR}/clawbot.env"

AIONIS_CONTAINER_NAME="${AIONIS_CONTAINER_NAME:-aionis-standalone-local}"
AIONIS_IMAGE="${AIONIS_IMAGE:-ghcr.io/cognary/aionis:standalone-v0.2.5}"
AIONIS_PORT="${AIONIS_PORT:-3001}"
AIONIS_VOLUME="${AIONIS_VOLUME:-aionis-standalone-data}"

EMBEDDING_PROVIDER="${EMBEDDING_PROVIDER:-fake}"
MINIMAX_API_KEY="${MINIMAX_API_KEY:-}"
MINIMAX_GROUP_ID="${MINIMAX_GROUP_ID:-}"
MINIMAX_EMBED_MODEL="${MINIMAX_EMBED_MODEL:-embo-01}"
MINIMAX_EMBED_TYPE="${MINIMAX_EMBED_TYPE:-db}"
MINIMAX_EMBED_ENDPOINT="${MINIMAX_EMBED_ENDPOINT:-https://api.minimax.chat/v1/embeddings}"

need() {
  command -v "$1" >/dev/null 2>&1 || {
    echo "missing required command: $1" >&2
    exit 1
  }
}

random_token() {
  need openssl
  openssl rand -base64 48 | tr '+/' '-_' | tr -d '=' | cut -c1-64
}

extract_api_key() {
  local raw="$1"
  printf "%s" "$raw" | sed -E 's/^\{"([^"]+)".*/\1/'
}

wait_health() {
  local url="$1"
  local max_tries=30
  local try=1
  while [[ $try -le $max_tries ]]; do
    if curl -fsS "$url" >/dev/null 2>&1; then
      return 0
    fi
    sleep 1
    try=$((try + 1))
  done
  return 1
}

write_env_file() {
  local memory_api_key="$1"
  local admin_token="$2"

  {
    echo "NODE_ENV=production"
    echo "APP_ENV=prod"
    echo "AIONIS_MODE=service"
    echo "PORT=3001"
    echo "TRUST_PROXY=false"
    echo
    echo "MEMORY_AUTH_MODE=api_key"
    echo "MEMORY_API_KEYS_JSON={\"${memory_api_key}\":{\"tenant_id\":\"default\",\"agent_id\":\"clawbot\",\"team_id\":\"default\"}}"
    echo "ADMIN_TOKEN=${admin_token}"
    echo
    echo "EMBEDDING_PROVIDER=${EMBEDDING_PROVIDER}"
    echo "EMBEDDING_DIM=1536"
    if [[ "${EMBEDDING_PROVIDER}" == "minimax" ]]; then
      echo "MINIMAX_API_KEY=${MINIMAX_API_KEY}"
      echo "MINIMAX_GROUP_ID=${MINIMAX_GROUP_ID}"
      echo "MINIMAX_EMBED_MODEL=${MINIMAX_EMBED_MODEL}"
      echo "MINIMAX_EMBED_TYPE=${MINIMAX_EMBED_TYPE}"
      echo "MINIMAX_EMBED_ENDPOINT=${MINIMAX_EMBED_ENDPOINT}"
    fi
    echo
    echo "CORS_ALLOW_ORIGINS="
    echo "CORS_ADMIN_ALLOW_ORIGINS="
  } >"$ENV_FILE"
}

write_clawbot_env_file() {
  local memory_api_key="$1"
  local admin_token="$2"
  {
    echo "AIONIS_BASE_URL=http://127.0.0.1:${AIONIS_PORT}"
    echo "AIONIS_API_KEY=${memory_api_key}"
    echo "AIONIS_ADMIN_TOKEN=${admin_token}"
    echo "AIONIS_TENANT_ID=default"
    echo "AIONIS_SCOPE_PREFIX=clawbot"
  } >"$CLAWBOT_ENV_FILE"
}

need docker
need curl

if ! docker info >/dev/null 2>&1; then
  echo "docker daemon is not running or not accessible" >&2
  exit 1
fi

if [[ "${EMBEDDING_PROVIDER}" == "minimax" ]]; then
  if [[ -z "${MINIMAX_API_KEY}" || -z "${MINIMAX_GROUP_ID}" ]]; then
    echo "EMBEDDING_PROVIDER=minimax requires MINIMAX_API_KEY and MINIMAX_GROUP_ID" >&2
    exit 1
  fi
fi

mkdir -p "$RUNTIME_DIR"

memory_api_key=""
admin_token=""

if [[ -f "$ENV_FILE" ]]; then
  # shellcheck disable=SC1090
  source "$ENV_FILE"
  memory_api_key="$(extract_api_key "${MEMORY_API_KEYS_JSON:-}")"
  admin_token="${ADMIN_TOKEN:-}"
fi

if [[ -z "$memory_api_key" ]]; then
  memory_api_key="${AIONIS_MEMORY_API_KEY:-$(random_token)}"
fi

if [[ -z "$admin_token" ]]; then
  admin_token="${AIONIS_ADMIN_TOKEN:-$(random_token)}"
fi

write_env_file "$memory_api_key" "$admin_token"
write_clawbot_env_file "$memory_api_key" "$admin_token"

if ! docker image inspect "$AIONIS_IMAGE" >/dev/null 2>&1; then
  if ! docker pull "$AIONIS_IMAGE" >/dev/null; then
    echo "failed to pull image: ${AIONIS_IMAGE}" >&2
    echo "hint: set AIONIS_IMAGE to an available local image, or run docker login for private registry" >&2
    exit 1
  fi
fi

docker rm -f "$AIONIS_CONTAINER_NAME" >/dev/null 2>&1 || true

docker run -d \
  --name "$AIONIS_CONTAINER_NAME" \
  --restart unless-stopped \
  -p "127.0.0.1:${AIONIS_PORT}:3001" \
  --env-file "$ENV_FILE" \
  -v "${AIONIS_VOLUME}:/var/lib/postgresql/data" \
  "$AIONIS_IMAGE" >/dev/null

if ! wait_health "http://127.0.0.1:${AIONIS_PORT}/health"; then
  echo "aionis standalone failed health check; inspect logs:" >&2
  echo "docker logs ${AIONIS_CONTAINER_NAME}" >&2
  exit 1
fi

echo "Aionis standalone is running."
echo "Container: ${AIONIS_CONTAINER_NAME}"
echo "Base URL: http://127.0.0.1:${AIONIS_PORT}"
echo "Skill env file: ${CLAWBOT_ENV_FILE}"
echo
echo "Export for current shell:"
echo "source ${CLAWBOT_ENV_FILE}"


path: README.md
content: # ClawHub Publish Notes

This folder is a publish-ready OpenClaw skill package.

## Contents

1. `SKILL.md` - skill definition and runtime guidance.
2. `AIONIS_ENV_TEMPLATE.txt` - local standalone defaults.
3. `bootstrap-local-standalone.sh` - one-click local install/start script.

## Local Standalone First (Required)

One-click bootstrap:

```bash
bash ./bootstrap-local-standalone.sh
```

The script creates:

1. `.runtime/aionis.env` for container runtime
2. `.runtime/clawbot.env` for Clawbot skill variables

Manual start (equivalent):

```bash
docker run -d --name aionis-standalone-local --restart unless-stopped \
  -p 127.0.0.1:3001:3001 \
  --env-file ./.runtime/aionis.env \
  -v aionis-standalone-data:/var/lib/postgresql/data \
  ghcr.io/cognary/aionis:standalone-v0.2.5
```

Health check:

```bash
curl -fsS http://127.0.0.1:3001/health
```

Auth check (`x-api-key`):

```bash
curl -sS http://127.0.0.1:3001/v1/memory/write \
  -H 'content-type: application/json' \
  -H 'x-[REDACTED_SECRET]' \
  -d '{"tenant_id":"default","scope":"default","input_text":"clawbot local standalone test"}'
```

## Publish

```bash
npm i -g clawhub
clawhub login
clawhub whoami

clawhub publish . \
  --slug aionis-memory-policy-loop \
  --name "Aionis Memory Policy Loop" \
  --version 1.0.0 \
  --changelog "Initial release" \
  --tags latest
```

## Update

```bash
clawhub publish . \
  --slug aionis-memory-policy-loop \
  --name "Aionis Memory Policy Loop" \
  --version 1.0.1 \
  --changelog "Fix prompt and examples" \
  --tags latest
```


path: AIONIS_ENV_TEMPLATE.txt
content: AIONIS_BASE_URL=http://127.0.0.1:3001
# If Clawbot runs inside another container, use:
# AIONIS_BASE_URL=http://host.docker.internal:3001

# Choose one auth mode
AIONIS_API_KEY=replace_me
# AIONIS_AUTH_BEARER=replace_me

AIONIS_TENANT_ID=default
AIONIS_SCOPE_PREFIX=clawbot


Security scan verdicts — ClawScan: suspicious | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (MEDIUM)