{"id":50146764,"url":"https://github.com/mmmarcinho/amotion","last_synced_at":"2026-05-24T05:08:42.819Z","repository":{"id":358931184,"uuid":"1243459354","full_name":"MMMarcinho/amotion","owner":"MMMarcinho","description":"Emotion Runtime Layer for LLM Agents","archived":false,"fork":false,"pushed_at":"2026-05-19T16:43:05.000Z","size":53,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-19T19:57:41.466Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MMMarcinho.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-19T11:09:25.000Z","updated_at":"2026-05-19T16:43:10.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/MMMarcinho/amotion","commit_stats":null,"previous_names":["mmmarcinho/amotion"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/MMMarcinho/amotion","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MMMarcinho%2Famotion","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MMMarcinho%2Famotion/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MMMarcinho%2Famotion/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MMMarcinho%2Famotion/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MMMarcinho","download_url":"https://codeload.github.com/MMMarcinho/amotion/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MMMarcinho%2Famotion/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33422099,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-23T22:14:44.296Z","status":"online","status_checked_at":"2026-05-24T02:00:06.296Z","response_time":57,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-05-24T05:08:25.596Z","updated_at":"2026-05-24T05:08:42.814Z","avatar_url":"https://github.com/MMMarcinho.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# amotion\n\nRuntime control layer for LLM agents.\n\namotion converts an agent's **operating signals** into runtime control policy.\nThe signals are observable execution facts — tool errors, retries, failed\nverifications, retrieval misses, stalls, low self-reported confidence — not\ninferred feelings. The runtime turns them into mechanical control decisions:\n**proceed / verify / replan / escalate / abort**.\n\n## Core Idea\n\n\u003e Emotion is not expression. Emotion is runtime resource allocation.\n\nThe \"affective state\" amotion tracks is the **agent's own operating state**,\nderived from what the run actually did. That makes every decision auditable\nagainst the trace: an agent that keeps failing accrues `friction`, loses\n`momentum`, and the runtime escalates or stops it instead of grinding forever.\n\nUser emotion is supported too, but only as an **optional external signal** that\ncan make the agent more cautious — never as the thing that drives the loop.\n\n## Pipeline\n\n```text\nAgent execution telemetry        (optional) User affect\n        |                                 |\n        v                                 v\n   Operating Signals  ----------------\u003e AgentRuntime\n                                          |\n                              Operating State (uncertainty,\n                              friction, confidence, momentum, load)\n                                          |\n                                          v\n                              Operating Policy  (proceed / verify /\n                              replan / escalate / abort, retry budget,\n                              verification \u0026 confirmation gates, autonomy)\n```\n\n## What Operating State Drives\n\n- control decision (proceed / verify / replan / escalate / abort)\n- retry budget (fewer retries as friction rises — forces a strategy change)\n- verification \u0026 human-confirmation gates\n- planning horizon and step bounds\n- tool-use threshold\n- autonomy\n- a deterministic circuit-breaker (consecutive failures / budget exhaustion)\n\n## Install\n\n```sh\npnpm add amotion\n```\n\n## Usage — agent operating runtime\n\n```ts\nimport { AgentRuntime } from \"amotion\";\n\nconst rt = new AgentRuntime();\n\nwhile (true) {\n  const result = runOneStep();\n  const policy = rt.tick(\n    result.ok ? { type: \"tool_success\" } : { type: \"tool_error\" }\n  );\n\n  if (policy.stop) break;                 // circuit-breaker tripped\n  if (policy.control === \"escalate\") askHuman();\n  if (policy.requireVerification) verifyBeforeActing();\n}\n```\n\nSee [`examples/agent-loop`](./examples/agent-loop) for a runnable comparison\nof a naive loop vs. a runtime-governed loop on a flaky tool.\n\n## Usage — optional user-affect signal\n\nThe original user-affect path still exists. Treat its output as one external\ninput that nudges caution, not as ground truth about the user's mind.\n\n```ts\nimport { Amotion, policyToSystemHint } from \"amotion\";\n\nconst amotion = new Amotion();\nconst result = await amotion.process({ message: \"我现在有点焦虑，不知道该怎么办\" });\nconst hint = policyToSystemHint(result.policy);\n```\n\n## Design Principle\n\namotion does not directly control the LLM.\nIt outputs runtime policy.\nThe agent's loop (or an adapter) translates policy into concrete behavior.\n\n## Optional: User-Affect Analyzer\n\nThis is the **external, optional** signal path. It estimates user emotion from\ntext and exposes it as a caution input to the runtime. It is inherently noisy\nand culturally loaded — see [EVALUATION.md](./EVALUATION.md) for how its\nfidelity is measured and [ROADMAP.md](./ROADMAP.md) for where it fits.\n\nThe analyzer is `TransformerEmotionAnalyzer`.\n\nIt uses Transformers.js (`@huggingface/transformers`) with a local ONNX text-classification model:\n\n```ts\nimport { TransformerEmotionAnalyzer } from \"amotion\";\n\nconst analyzer = new TransformerEmotionAnalyzer({\n  model: \"onnx-community/tanaos-emotion-detection-v1-ONNX\",\n});\n```\n\nThe classifier output is mapped into amotion runtime dimensions such as `stress`, `uncertainty`, `engagement`, `trust`, `valence`, `arousal`, and `dominance`.\n\nThe first run downloads model files from Hugging Face unless the model is already cached or `pipelineOptions.local_files_only` is enabled.\n\nIf you use a mirror, set `HF_ENDPOINT` before running the app:\n\n```sh\nHF_ENDPOINT=https://hf-mirror.com pnpm --filter @amotion/basic-node dev\n```\n\nYou can also configure it in code:\n\n```ts\nconst analyzer = new TransformerEmotionAnalyzer({\n  remoteHost: \"https://hf-mirror.com\",\n});\n```\n\nTo run against a manually downloaded local model:\n\n```sh\nAMOTION_MODEL=/Users/marco/github/models/tanaos-emotion-detection-v1-ONNX \\\nAMOTION_LOCAL_FILES_ONLY=true \\\npnpm --filter @amotion/basic-node dev\n```\n\nFor richer fine-grained labels, you can configure a GoEmotions ONNX model:\n\n```ts\nconst analyzer = new TransformerEmotionAnalyzer({\n  model: \"SamLowe/roberta-base-go_emotions-onnx\",\n});\n```\n\n`RuleAnalyzer` still exists only as a lightweight fallback when local model loading is unavailable. It is not the primary analyzer.\n\n## Packages\n\n- `amotion`: core schema, analyzer, state manager, policy mapper, runtime class, and prompt hint helper.\n- `@amotion/adapters`: framework-neutral adapter helpers for generic agents and future framework integrations.\n\n## Development\n\n```sh\npnpm install\npnpm test\npnpm build\npnpm --filter @amotion/basic-node dev\npnpm --filter @amotion/playground dev\n```\n\n## Evaluation Design\n\nThe primary evaluation plan lives in [EVALUATION.md](./EVALUATION.md).\nThe implementation sketch lives in [docs/EVAL_DESIGN.md](./docs/EVAL_DESIGN.md).\n\nIt separates two questions:\n\n- whether operating telemetry produces the right control decisions\n- whether optional user-affect signals produce useful caution adjustments\n\nThe executable trace replay harness and sample fixtures live in [evals/](./evals/).\n\n## MVP Non-goals\n\n- clinical emotion diagnosis\n- mental health advice\n- anthropomorphic claims\n- provider LLM integrations in core\n- training pipeline\n\n## Roadmap\n\nSee [ROADMAP.md](./ROADMAP.md) for the full plan.\n\n- v0.2: finish the agent operating runtime and document every control decision.\n- v0.3: add trace replay, eval fixtures, and the `@amotion/eval` scaffold.\n- v0.4: ship a real agent adapter that consumes `OperatingPolicy`.\n- v0.5: run end-to-end A/B experiments against blind control loops.\n- v1.0: freeze the public runtime interfaces and publish benchmark results.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmmmarcinho%2Famotion","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmmmarcinho%2Famotion","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmmmarcinho%2Famotion/lists"}