Use Custom to supplement logic that cannot be expressed by Pipeline: reading external state, cross-node data transfer, dynamic counting, complex judgments, and custom recognition algorithms.
Do not write binding class signatures and context API from memory — always route to the bindings / native-api index of
MaaLLMWiki (version locked, source-referenced; when the
skill is installed, it will handle the complete routing process).
-
Determine host and registration path (prior to all implementation decisions): Whether in-process registration is possible is determined by who owns the main program — see references/agent-mode.md for details, agent segment wiring and architecture.
-
Type Determination:
- Custom recognition algorithm → ( returns hit box);
- External calls / complex actions → ( returns success or failure);
- Cross-cutting hooks (global checks, failure guidance) → sink channel instead of scattered into actions (see "Event Listening" in patterns.md for details).
Special cases are not included in the above categories: Non-standard device control uses
— it is accessed as a
controller rather than registered (subclass + factory constructed and then bound to Tasker), and is only feasible when you control the host process; the framework does not provide controller creation in the agent child process (see agent capabilities in agent-mode.md).
-
Minimum Registration Closed Loop: First connect the minimum node (DoNothing + logs) to get through the "registration → pipeline reference → being called" flow, then fill in the implementation.
-
File Creation and Implementation:
- Split files by business capability, aligned with the module directory of resource (file form follows language idioms, see "Module Boundaries" in references/patterns.md for criteria);
- Common reusable components go into the shared component directory; register at a single registration point (decorator or centralized registry);
- Parameters enter from pipeline's / (JSON), and are used after being processed for type / required / default values and runtime validation by parsing utility functions, do not take fields directly; the implementation comes with behavior contract documentation (docstring / comments and other language conventions) — clearly write expected behavior and parameter semantics.
-
Reuse instead of Rewrite:
- When recognition / action is needed in custom, prioritize referencing existing pipeline nodes —
context.run_recognition("<node_name>", image)
directly runs the recognition of a node;
- Image source depends on usage: use for the current screen in recognition callback; for a new screen after an action, actively take a screenshot through the existing controller and get the image after it is completed (example form
context.tasker.controller.post_screencap().wait().get()
, name is subject to binding routing); belongs to the controller, is the cache of the latest completed screenshot, and will not refresh by itself — use only when timeliness is acceptable;
- The recognize → operate → re-recognize rule also applies in custom (see flow-patterns of maafw-pipeline).
-
Failure, Cancellation and State Scope: See Hard Guardrail 2 for the three failure semantics; see Hard Guardrail 4 for cancellation strategies for long loops and external IO; indicate the lifecycle of cross-call state (Hard Guardrail 5); specify the target, scope and lifecycle of override patches (see "State and Scope" in patterns.md).
-
Validation: Logs include node name + input parameter summary + result summary (this is the only clue for troubleshooting); after unit validation, proceed to
for single-node flow and end-to-end testing.