clara

Juan José Vázquez Delgado 2025-10-06T11:51:33.520479Z

Hello everyone. Starting with Clara Rules. It's an amazing tool. Thanks for all the work done here. However, I'm having trouble configuring the linters with clj-kondo so it doesn't complain about the defrule macro. Running clj-kondo --lint $(clj -Spath) --copy-configs in the project root configures the linter to the point where it recognizes everything except the docstring. clj-kondo complains with: Function name must be simple symbol but got: "this is the docstring". Any help? Thanks!

👀 2
jgomez 2025-10-26T01:10:51.554799Z

Juan if you want to provide some example code I can try to help, I wrote the clj-kondo linter for Clara and I thought it was pretty up to date, but all my contributions in recent years are here instead: https://github.com/k13labs/clara-rules, you can always copy the linter and add it to your project and make any changes you want. Last I checked though, docstrings work fine, but maybe you have run into an edge case?

2026-04-27T15:07:56.284129Z

Just FYI: I forked off with https://github.com/mrrodriguez/concrete-rules which I removed CLJS support for and made a deployment with the lint fixes (I know that jgomez did similar earlier). See the README there. I am interesting in exploring some future usages of the CLJ-side, but for now it is the same except with linting cleanup and the CLJS removal.

jgomez 2026-04-27T15:16:09.463579Z

yeah, my fork lives here now: https://github.com/gateless/clara-rules, I've gone a bit beyond just removing CLJS at this point, if you'd like to chat sometime @mikerod let me know maybe our goals align?

2026-04-27T15:17:21.383049Z

Sure. Feel free to DM if that's easier to discuss draft thoughts.

eraserhd 2026-04-27T17:53:39.204829Z

Discuss here! I doubt anyone is looking at it, but for reference, the one big feature I've always wanted from Clara Rules is the ability to assert new rules at runtime. Some older, larger forward-chaining systems have this.

2026-04-27T18:04:14.592889Z

Yeah, we can keep things updated here if anything interesting is arrived at. I think at first it was just a sync to see if goals aligned well enough etc. Dynamically adding rules is an interesting idea too. I think that's probably feasible, but would have to consider the implications with TMS and durability etc. I'm open to issues/prs on the concrete-rules in the meantime to consider things, but it's worth considering changes that Jose has made on the gateless fork for those interested I think.

ethanc 2026-04-27T18:15:28.549869Z

> consider the implications with TMS and durability etc. Gut says that TMS is the sticky bit here, as it would somewhat imply that you’d have to make a decision between: 1. Keep all facts for ever, regardless of matching 2. Agree that only facts seen after the rule is added should remain the former causes bloat in memory, the latter makes it challenging to track/understand why specific logic did/didn’t apply

2026-04-27T18:24:53.406339Z

Ah yeah. I forgot about that implication we discussed long ago. I think I originally considered that you'd have to start the network in a "mode" that supports adding rules. In that "mode" it would retain all facts in memory - therefore causing the bloat to be aware of. It could also have an option to not retain all facts if you thought the domain would not be confusing with that logic.

2026-04-27T18:25:08.073779Z

The trick would be to do it this without rippling tons of complexity all over the impl I think.

ethanc 2026-04-27T18:32:44.462939Z

“static” vs “dynamic” rulebase mode is an interesting thought, and would likely suffice. I would imagine that additional rules with the current implementation would encounter some interesting performance characteristics if the 8-ball was needed to be shaken entirely again….

👍 1
jgomez 2026-04-27T18:35:45.821279Z

I'd like to understand the problem a bit better, is it truly about just modifying an existing session or more about modifying a running session while it is in the middle of running (thus at runtime)

jgomez 2026-04-27T18:36:38.243479Z

@eraserhd can you explain a bit better what you mean just to make sure I don't misunderstand it? Maybe provide an example, I'm not promising to work on it but good to understand the problem first.

2026-04-27T18:43:11.862719Z

Good point. Just a few more notes: 1. My thoughts on it before that I didn't mention was that I was only considering adding rules/queries to a session in a stable state - not during the fire-rules loop. 2. I've often opted-out of this approach by instead suggesting that you have one session return suitable higher-level facts from the existing rules and send those facts to a new session with your new rules that can further refine the criteria, rather than to update-in-place the existing session's productions and memory.

👍 1
jgomez 2026-04-27T18:50:41.223809Z

yeah that's why I wanted some clarification, because if one feels like one needs to change the running rules during fire-rules it is often another problem masking as the need to change the running rules at runtime, if it is however changing a persistent session before fire-rules is invoked again that's probably doable but it wouldn't be free either, we solve that problem by just creating a fresh session whenever rules change at runtime. In a way clara already supports changing the rules at runtime because you can implement your own rules loader, which could load rules from a database (or in our case we load them from S3 blobs), then run rules with that, which would in turn create a new session with the updated rules. The fork of clara that I maintain adds two key things to support rules changing at runtime as described above: • a first class session cache (using clojure.core.cache that can be provided), which caches the session as long as rules don't change. • a first class compiler cache (also using clojure.core.cache), which caches compiled expressions, this one is an optimization that makes the mk-session faster when some expressions change but not all, making it so that only the LHS/RHS expressions that changed are re-compiled.

jgomez 2026-04-27T18:54:22.198599Z

the key thing is to realize one does not have to load rules from namespaces

eraserhd 2026-04-27T18:58:42.971719Z

We had complicated sets of rules that we built from macros on top of macros, which consumed static data, and this just felt wrong. While I generally am happy to slather a thin layer of macros on top of some nice but verbose abstractions, leaving the more verbose API available for others to build on, stacking macros tends to suggest something wrong... I did not know about rules loaders, is that in the official Clara?

eraserhd 2026-04-27T19:00:14.886809Z

In any case, I did not consider about the fact retention problem, but I was thinking about asserting rules as facts in some way. I forgot which system I read about that does this? S-something? This seemed like a more Clojure-like workflow that doesn't enforce a ... sort of compile/runtime separation.

jgomez 2026-04-27T19:07:32.458679Z

yeah rules loader is a protocol that anything can implement, then you can just pass that instead of a namespace symbol, in fact here's the symbol/namespace implementation: https://github.com/oracle-samples/clara-rules/blob/878c877ad4165386c1771a86c8343e29b494adf9/src/main/clojure/clara/rules.cljc#L274 (loads rules and queries I changed this a bit of my fork even going as far as renaming the protocol because I load not only rules but also it is the same idea: https://github.com/gateless/clara-rules/blob/main/src/main/clojure/clara/rules.clj#L144 - loads rules, queries and hierarchies (derive/underive fact hierarchy)

jgomez 2026-04-27T19:08:12.820069Z

for example in our production rules pipeline we have an implementation of the above that loads rules from S3, if we want to update the rules we can just upload a new blob to S3 without re-deploying the service

2025-10-09T15:04:03.215289Z

I haven’t looked into this but thought there was work done here not long back. I suspect if you have a PR do fix it that would be applied without much friction.

jose 2026-03-21T14:44:42.376589Z

There is already a PR to fix it: https://github.com/oracle-samples/clara-rules/pull/505 But it's already 1.5 years old...

jgomez 2026-03-21T14:54:29.997819Z

I think only Ethan is left with maintainer access to that repo

2026-03-21T15:05:28.512049Z

Yeah it is @ethanc I believe. I approved the lint PR. I'll see if he wants to look at it/merge.

👍 1