diff --git a/src/box/lua/tuple.lua b/src/box/lua/tuple.lua
index eb3946a0f5c5b56372d0157b349297d155666e8d..f97aa157964ebd9fec5058522c2c0866e956065e 100644
--- a/src/box/lua/tuple.lua
+++ b/src/box/lua/tuple.lua
@@ -352,7 +352,8 @@ internal.tuple.tostring = nil
 internal.tuple.bless = tuple_bless
 internal.tuple.encode = tuple_encode
 
--- The function is internal in a sense that it is not documented.
--- But it is safe and widely used in the tests. Keep it here at
--- least for test code.
+-- Public API, additional to implemented in C.
+
+-- is() is implemented in Lua, because then it is
+-- easy to be JITed.
 box.tuple.is = is_tuple
diff --git a/test/box/tuple.result b/test/box/tuple.result
index 78f919deba3655725d7043eca8d479076986d8be..a499aa43ad270876a4d7ee377c0436374fec9daa 100644
--- a/test/box/tuple.result
+++ b/test/box/tuple.result
@@ -1450,6 +1450,46 @@ level == max_depth + 5 or {level, max_depth}
 ---
 - true
 ...
+-- gh-4684: some box.tuple.* methods were private and could be
+-- used by customers to shoot in their own legs. Some of them
+-- were moved to a more secret place. box.tuple.is() was moved to
+-- the public API, legally.
+box.tuple.is()
+---
+- false
+...
+box.tuple.is(nil)
+---
+- false
+...
+box.tuple.is(box.NULL)
+---
+- false
+...
+box.tuple.is({})
+---
+- false
+...
+box.tuple.is(ffi.new('char[1]'))
+---
+- false
+...
+box.tuple.is(1)
+---
+- false
+...
+box.tuple.is('1')
+---
+- false
+...
+box.tuple.is(box.tuple.new())
+---
+- true
+...
+box.tuple.is(box.tuple.new({1}))
+---
+- true
+...
 msgpack.cfg({encode_max_depth = max_depth, encode_deep_as_nil = deep_as_nil})
 ---
 ...
diff --git a/test/box/tuple.test.lua b/test/box/tuple.test.lua
index baf2f22d5b38b63999812925a65cdf8547e538de..b83fca5cdf40288fcad173d362cbd9a6e7cffdd1 100644
--- a/test/box/tuple.test.lua
+++ b/test/box/tuple.test.lua
@@ -496,4 +496,18 @@ while tuple ~= nil do level = level + 1 tuple = tuple[1] end
 -- serializer allows deeper tables.
 level == max_depth + 5 or {level, max_depth}
 
+-- gh-4684: some box.tuple.* methods were private and could be
+-- used by customers to shoot in their own legs. Some of them
+-- were moved to a more secret place. box.tuple.is() was moved to
+-- the public API, legally.
+box.tuple.is()
+box.tuple.is(nil)
+box.tuple.is(box.NULL)
+box.tuple.is({})
+box.tuple.is(ffi.new('char[1]'))
+box.tuple.is(1)
+box.tuple.is('1')
+box.tuple.is(box.tuple.new())
+box.tuple.is(box.tuple.new({1}))
+
 msgpack.cfg({encode_max_depth = max_depth, encode_deep_as_nil = deep_as_nil})