dev/familiar-add-tool/SKILL.md
Scaffold a new sensor/actuator tool for familiar-ai. Generates the tool file and registers it in all required places in agent.py.
npx skillsauth add lifemate-ai/familiar-ai familiar-add-toolInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Scaffold a new tool (sensor, actuator, or service) for the familiar-ai agent.
src/familiar_agent/tools/<name>.py from the standard templateagent.py in all three required placesconfig.py and .env.exampleagent.pyAsk the user (or infer from context):
microphone)listen, record)MIC_DEVICE_INDEX)Create src/familiar_agent/tools/<name>.py:
"""<Name> tool — <one-line description>."""
from __future__ import annotations
import logging
logger = logging.getLogger(__name__)
class <Name>Tool:
"""<Description>."""
def __init__(self, <config_params>) -> None:
self.<param> = <param>
# TODO: initialize hardware/client
async def <verb>(self, <args>) -> tuple[str, str | None]:
"""<What this action does>. Returns (text_result, image_b64_or_None)."""
# TODO: implement
return "Not implemented yet.", None
def get_tool_definitions(self) -> list[dict]:
return [
{
"name": "<verb>",
"description": "<What the agent does when calling this tool>.",
"input_schema": {
"type": "object",
"properties": {
# "<param>": {"type": "string", "description": "..."},
},
"required": [],
},
},
]
async def call(self, tool_name: str, tool_input: dict) -> tuple[str, str | None]:
if tool_name == "<verb>":
return await self.<verb>(**tool_input)
return f"Unknown tool: {tool_name}", None
Key rules for tool files:
call() always returns tuple[str, str | None] — text result + optional JPEG base64get_tool_definitions() uses Anthropic input_schema formatagent.pyTouch three places:
from .tools.<name> import <Name>Tool
_init_tools() — instantiate if config is available# In Agent._init_tools():
<name>_cfg = self.config.<name> # or read directly from config
if <name>_cfg.<required_field>:
self._<name> = <Name>Tool(<name>_cfg.<field>, ...)
_all_tool_defs property — expose definitions# In Agent._all_tool_defs:
if self._<name>:
defs.extend(self._<name>.get_tool_definitions())
_execute_tool() — route calls# In Agent._execute_tool():
<name>_tools = {"<verb1>", "<verb2>"}
if name in <name>_tools and self._<name>:
return await self._<name>.call(name, tool_input)
Also add self._<name>: <Name>Tool | None = None to __init__.
config.pyIf new env vars are needed, add a config dataclass:
@dataclass
class <Name>Config:
<field>: str = field(default_factory=lambda: os.environ.get("<ENV_VAR>", ""))
And add it to AgentConfig:
<name>: <Name>Config = field(default_factory=<Name>Config)
agent.pyAdd the tool to the body parts description in SYSTEM_PROMPT:
- <Body part name> (<verb>): <How the agent should think about and use this>.
Keep it grounded and concrete — e.g. "Ears (listen): Your hearing. Calling listen() records audio from the microphone and transcribes it."
.env.example# <Name> tool
<ENV_VAR>=
tools/<name>.py created with get_tool_definitions() and call()agent.py_init_tools() instantiates the tool (with optional guard)_all_tool_defs includes it_execute_tool() routes to itconfig.py has new config class (if needed)AgentConfig references the new config (if needed)SYSTEM_PROMPT describes the new body part.env.example documents new env varsuv run ruff check . && uv run ruff format . before committingtools
Debug a stuck or misbehaving familiar-ai ReAct loop. Diagnoses tool-call failures, model output issues, prompt-mode parsing errors, and silent tool skips.
tools
Validate the .env configuration for familiar-ai. Detects common misconfigurations like wrong ports, missing MODEL, or TOOLS_MODE issues that cause silent failures or timeouts.
tools
Use when work should span one or more detached tasks but still behave like one job with a single owner context. TaskFlow is the durable flow substrate under authoring layers like Lobster, ACPX, plugins, or plain code. Keep conditional logic in the caller; use TaskFlow for flow identity, child-task linkage, waiting state, revision-checked mutations, and user-facing emergence.
tools
# Lobster Lobster executes multi-step workflows with approval checkpoints. Use it when: - User wants a repeatable automation (triage, monitor, sync) - Actions need human approval before executing (send, post, delete) - Multiple tool calls should run as one deterministic operation ## When to use Lobster | User intent | Use Lobster? | | ------------------------------------------------------ | --------------------------