{"id":17347526,"url":"https://github.com/cryptiklemur/fluent-behavior-tree","last_synced_at":"2026-03-07T09:33:24.171Z","repository":{"id":41203498,"uuid":"113135521","full_name":"cryptiklemur/fluent-behavior-tree","owner":"cryptiklemur","description":"Typescript/Javascript behavior tree library with a fluent API","archived":false,"fork":false,"pushed_at":"2020-09-24T19:52:22.000Z","size":59,"stargazers_count":72,"open_issues_count":2,"forks_count":11,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-04-14T20:55:34.303Z","etag":null,"topics":["behavior-tree","behavior-trees","behaviour-tree","behaviour-trees","typescript","typescript-library"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cryptiklemur.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-12-05T05:10:01.000Z","updated_at":"2025-03-19T09:55:14.000Z","dependencies_parsed_at":"2022-09-12T13:25:43.322Z","dependency_job_id":null,"html_url":"https://github.com/cryptiklemur/fluent-behavior-tree","commit_stats":null,"previous_names":["cryptiklemur/fluent-behavior-tree","aequasi/fluent-behavior-tree"],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/cryptiklemur/fluent-behavior-tree","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cryptiklemur%2Ffluent-behavior-tree","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cryptiklemur%2Ffluent-behavior-tree/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cryptiklemur%2Ffluent-behavior-tree/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cryptiklemur%2Ffluent-behavior-tree/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cryptiklemur","download_url":"https://codeload.github.com/cryptiklemur/fluent-behavior-tree/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cryptiklemur%2Ffluent-behavior-tree/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30210852,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-07T09:02:10.694Z","status":"ssl_error","status_checked_at":"2026-03-07T09:02:08.429Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["behavior-tree","behavior-trees","behaviour-tree","behaviour-trees","typescript","typescript-library"],"created_at":"2024-10-15T16:49:06.233Z","updated_at":"2026-03-07T09:33:24.152Z","avatar_url":"https://github.com/cryptiklemur.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Fluent Behavior Tree\n[![Build Status](https://travis-ci.org/aequasi/fluent-behavior-tree.svg?branch=master)](https://travis-ci.org/aequasi/fluent-behavior-tree) [![npm version](https://badge.fury.io/js/fluent-behavior-tree.svg)](https://badge.fury.io/js/fluent-behavior-tree)\n\nThis is a Typescript/Javascript implementation of https://github.com/codecapers/Fluent-Behaviour-Tree\n\nJS/TS behaviour tree library with a fluent API.\n\nFor a background and walk-through please see [the accompanying article](http://www.what-could-possibly-go-wrong.com/fluent-behavior-trees-for-ai-and-game-logic/).\n\n## Understanding Behaviour Trees\n\nHere are some resources to help you understand behaviour trees:\n\n- [Behaviour tree (Wikipedia)](https://en.wikipedia.org/wiki/Behavior_tree_(artificial_intelligence,_robotics_and_control))\n- [Behavior trees for AI: How they work](http://www.gamasutra.com/blogs/ChrisSimpson/20140717/221339/Behavior_trees_for_AI_How_they_work.php)\n- [Understanding Behaviour Trees](http://aigamedev.com/open/article/bt-overview/)\n- [Introduction and implementation of Behaviour Trees](http://guineashots.com/2014/07/25/an-introduction-to-behavior-trees-part-1/)\n\n## Installation\n\nInstall with npm:\n\n```shell\nnpm install -s fluent-behavior-tree\n```\n\n## Usage\n\nA behavior tree is created through *BehaviorTreeBuilder*. The tree is returned when the *build* function is called.\n\n```\nimport {BehaviorTreeBuilder, BehaviorTreeStatus, TimeData} from \"fluent-behavior-tree\";\n\n// ...\n\nconst builder = new BehaviorTreeBuilder();\nthis.tree = builder\n    .sequence(\"my-sequence\")\n        .do(\"action1\", async (t) =\u003e {\n            // Action 1.\n\n            return BehaviorTreeStatus.Success;\n        })\n        .do(\"action2\", async (t) =\u003e {\n            //Action 2.\n\n            return BehaviorTreeStatus.Failure;\n        })\n    .end()\n    .build();\n```\n\nThen, *Tick* the behavior tree on each *update* of your *loop*\n\n```\npublic async update(deltaTime: number): Promise\u003cvoid\u003e {\n    await this.tree.tick(new TimeData(deltaTime));\n}\n```\n\n## Behavior Tree Status\n\nBehavior tree nodes must return the following status codes:\n\n* *BehaviorTreeStatus.Success*: The node has finished what it was doing and succeeded.\n* *BehaviorTreeStatus.Failure*: The node has finished, but failed.\n* *BehaviorTreeStatus.Running*: The node is still working on something.\n\n## Node Types\n\n### Action / Leaf-Node\n\nCall the *do* function to create an action node at the leaves of the behavior tree.\n\n```\n.do(\"do-something\", async (t) =\u003e {\n    // ... Do something ...\n\n    return BehaviorTreeStatus.Success;\n});\n```\n\nThe return value defines the status of the node. Return one of the statuses from above.\n\n### Sequence\n\nRuns each child node in sequence. Fails for the first child node that *fails*. Moves to the next child when the current running child *succeeds*. Stays on the current child node while it returns *running*. Succeeds when all child nodes have succeeded.\n\n```\n.sequence(\"my-sequence\")\n    .do(\"action1\", async (t) =\u003e { // Run this.\n        // Action 1.\n\n        return BehaviorTreeStatus.Success;\n    })\n    .do(\"action2\", async (t) =\u003e { // Then run this.\n        //Action 2.\n\n        return BehaviorTreeStatus.Failure;\n    })\n.end()\n```\n\n### Parallel\n\nRuns all child nodes in parallel. Continues to run until a required number of child nodes have either *failed* or *succeeded*.\n\n```\nlet numRequiredToFail: number = 2;\nlet numRequiredToSuccess: number = 2;\n\n.parallel(\"my-parallel\"m numRequiredtoFail, numRequiredToSucceed)\n    .do(\"action1\", async (t) =\u003e { // Run this at the same time as action2\n        // Parallel action 1\n\n        return BehaviorTreeStatus.Running;\n    })\n    .do(\"action12, async (t) =\u003e { // Run this at the same time as action1\n        // Parallel action 2\n\n        return BehaviorTreeStatus.Running;\n    })\n.end();\n```\n\n### Selector\n\nRuns child nodes in sequence until it finds one that *succeeds*. Succeeds when it finds the first child that *succeeds*. For child nodes that *fail*, it moves forward to the next child node. While a child is *running* it stays on that child node without moving forward.\n\n```\n.selector(\"my-selector\")\n    .do(\"action1\", async (t) =\u003e {\n        // Action 1\n\n        return BehaviorTreeStatus.Failure; // Fail, move onto the next child\n    })\n    .do(\"action2\", async (t) =\u003e {\n        // Action 2\n\n        return BehaviorTreeStatus.Success; // Success, stop here.\n    })\n    .do(\"action3\", async (t) =\u003e {\n        // Action 3\n\n        return BehaviorTreeStatus.Success; // Doesn't get this far.\n    })\n.end();\n```\n\n### Condition\n\nThe condition function is syntatic sugar for the *do* function. It allows the return of a boolean value that is then converted to *success* or *failure*. It is intended to be used with *Selector*.\n\n```\n.selector(\"my-selector\")\n    .Condition(\"condition1\", async (t) =\u003e this.someBooleanConditional()) // Predicate that returns *true* or *false*\n    .do(\"action1\", async (t) =\u003e this.someAction()) // Action to run if the predicate evaluates to *true*\n.end()\n```\n\n### Inverter\n\nInverts the *success* or *failure* of the child node. Continues running while the child node is *running*.\n\n```\n.inverter(\"inverter1\")\n    .do(\"action1\", async (t) =\u003e BehaviourTreeStatus.Success) // *Success* will be inverted to *failure*.\n.end()\n\n\n.inverter(\"inverter1\")\n    .do(\"action1\", async (t) =\u003e BehaviourTreeStatus.Failure) // *Failure* will be inverted to *success*.\n.end()\n```\n\n## Nesting Behaviour Trees\n\nBehaviour trees can be nested to any depth, for example:\n\n```\n.selector(\"parent\")\n    .sequence(\"child-1\")\n        ...\n        .parallel(\"grand-child\")\n            ...\n        .end()\n        ...\n    .end()\n    .sequence(\"child-2\")\n        ...\n    .end()\n.end()\n```\n\n## Splicing a Sub-tree\n\nSeparately created sub-trees can be spliced into parent trees. This makes it easy to build behaviour trees from reusable components.\n\n```\nprivate createSubTree(): BehaviorTreeNodeInterface\n{\n    return new BehaviourTreeBuilder()\n        .sequence(\"my-sub-tree\")\n            .do(\"action1\", async (t) =\u003e {\n                // Action 1.\n\n                return BehaviourTreeStatus.Success;\n            })\n            .Do(\"action2\", async (t) =\u003e {\n                // Action 2.\n\n                return BehaviourTreeStatus.Success;\n            });\n        .end()\n        .build();\n}\n\npublic startup(): void\n{\n    this.tree = new BehaviourTreeBuilder()\n        .sequence(\"my-parent-sequence\")\n            .Splice(this.createSubTree()) // Splice the child tree in.\n            .Splice(this.createSubTree()) // Splice again.\n        .end()\n        .build();\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcryptiklemur%2Ffluent-behavior-tree","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcryptiklemur%2Ffluent-behavior-tree","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcryptiklemur%2Ffluent-behavior-tree/lists"}