     |> do_call_action(fun, args)
   end
 
-  @spec do_call_action([t()], atom(), [term()]) :: Result.t()
-  defp do_call_action(plugins, fun, args)
+  @spec do_call_action([{integer(), t()}], atom(), [term()]) :: Result.t()
+  defp do_call_action(arity_and_plugins, fun, args)
   defp do_call_action([], _fun, _args), do: :ok
 
-  defp do_call_action([plugin | plugins], fun, args) do
-    case apply(plugin.module, fun, args) do
+  defp do_call_action([{arity, plugin} | arity_and_plugins], fun, args) do
+    new_args = update_callback_args(args, plugin, fun, arity)
+
+    case apply(plugin.module, fun, new_args) do
       :ok ->
-        do_call_action(plugins, fun, args)
+        do_call_action(arity_and_plugins, fun, args)
 
       {:error, _} = error ->
         error

    end
  rescue
    exception -> handle_exception(exception, plugin.module, fun)
  end

  @spec handle_exception(Exception.t(), atom(), atom()) :: Result.t()

    |> do_call_function(fun, args, arg)
  end

  @spec do_call_function([{integer, t()}], atom(), [term()], term()) :: Result.t(term())
  defp do_call_function(arity_and_plugins, fun, args, acc)
  defp do_call_function([], _fun, _args, acc), do: {:ok, acc}

  defp do_call_function([{arity, plugin} | arity_and_plugins], fun, args, acc) do
    new_args = update_callback_args(args, plugin, fun, arity)

    case apply(plugin.module, fun, [acc | new_args]) do
      {:ok, new_acc} ->
        do_call_function(arity_and_plugins, fun, args, new_acc)

      {:error, _} = error ->
        error
