diff --git a/src/main.rs b/src/main.rs
index 969ed8ce29bd47df87ff82363f98de6c2258f19e..b6b7bfcd5844b8fa1bc21e36d644615f90b06177 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -56,6 +56,39 @@ fn picolib_setup(args: &args::Run) {
     luamod.set("VERSION", env!("CARGO_PKG_VERSION"));
     luamod.set("args", args);
 
+    luamod.set(
+        "whoami",
+        tlua::function0(|| -> Result<_, Error> {
+            let node = traft::node::global()?;
+            let raft_storage = &node.storage.raft;
+
+            Ok(tlua::AsTable((
+                ("raft_id", raft_storage.raft_id()?),
+                ("cluster_id", raft_storage.cluster_id()?),
+                ("instance_id", raft_storage.instance_id()?),
+            )))
+        }),
+    );
+
+    luamod.set(
+        "peer_info",
+        tlua::function1(|iid: String| -> Result<_, Error> {
+            let node = traft::node::global()?;
+            let peer = node.storage.peers.get(&InstanceId::from(iid))?;
+
+            Ok(tlua::AsTable((
+                ("raft_id", peer.raft_id),
+                ("advertise_address", peer.peer_address),
+                ("instance_id", peer.instance_id.0),
+                ("instance_uuid", peer.instance_uuid),
+                ("replicaset_id", peer.replicaset_id),
+                ("replicaset_uuid", peer.replicaset_uuid),
+                ("current_grade", peer.current_grade),
+                ("target_grade", peer.target_grade),
+            )))
+        }),
+    );
+
     luamod.set(
         "raft_status",
         tlua::function0(|| traft::node::global().map(|n| n.status())),
diff --git a/test/int/test_basics.py b/test/int/test_basics.py
index 57c8f48fb32fb6c1e9d0f2b18946216044e64441..0e199994e6e21b3d8d3131a097e2065eb96362f7 100644
--- a/test/int/test_basics.py
+++ b/test/int/test_basics.py
@@ -173,3 +173,26 @@ def test_graceful_stop(instance: Instance):
     )
     with open(os.path.join(instance.data_dir, last_xlog), "rb") as f:
         assert f.read()[-4:] == b"\xd5\x10\xad\xed"
+
+
+def test_whoami(instance: Instance):
+    assert instance.call("picolib.whoami") == {
+        "raft_id": 1,
+        "instance_id": "i1",
+        "cluster_id": instance.cluster_id,
+    }
+
+
+def test_peer_info(instance: Instance):
+    def peer_info(iid: str):
+        return instance.call("picolib.peer_info", iid)
+
+    # Don't compare entire structure, a couple of fields is enough
+    myself = peer_info("i1")
+    assert myself["raft_id"] == 1
+    assert myself["instance_id"] == "i1"
+    assert myself["replicaset_id"] == "r1"
+
+    with pytest.raises(ReturnError) as e:
+        peer_info("i2")
+    assert e.value.args == ('peer with id "i2" not found',)
diff --git a/test/int/test_uninitialized.py b/test/int/test_uninitialized.py
new file mode 100644
index 0000000000000000000000000000000000000000..9e16a994aaef8ef77b365ebae73ab62a82f26d1d
--- /dev/null
+++ b/test/int/test_uninitialized.py
@@ -0,0 +1,44 @@
+import funcy  # type: ignore
+import pytest
+
+from typing import Any, Callable, Generator
+
+from conftest import (
+    eprint,
+    Cluster,
+    Instance,
+    ReturnError,
+)
+
+
+@pytest.fixture
+def uninitialized_instance(cluster: Cluster) -> Generator[Instance, None, None]:
+    """Returns a running instance that is stuck in discovery phase."""
+
+    # Connecting TCP/0 always results in "Connection refused"
+    instance = cluster.add_instance(peers=[":0"], wait_online=False)
+    instance.start()
+
+    @funcy.retry(tries=30, timeout=0.2)
+    def wait_running():
+        assert instance.eval("return box.info.status") == "running"
+        eprint(f"{instance} is running (but stuck in discovery phase)")
+
+    wait_running()
+    yield instance
+
+
+def test_raft_api(uninitialized_instance: Instance):
+    functions: list[Callable[[Instance], Any]] = [
+        lambda i: i._raft_status(),
+        lambda i: i.call("picolib.raft_propose_nop"),
+        lambda i: i.call("picolib.raft_propose_info", "who cares"),
+        lambda i: i.call("picolib.whoami"),
+        lambda i: i.call("picolib.peer_info", "i1"),
+        lambda i: i.call("picolib.peer_info", "i2"),
+    ]
+
+    for f in functions:
+        with pytest.raises(ReturnError) as e:
+            f(uninitialized_instance)
+        assert e.value.args == ("uninitialized yet",)